1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use16(i16)
5 declare void @use32(i32)
6 declare void @use64(i64)
8 define i32 @t0(i64 %data, i32 %nbits) {
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]]
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
38 define 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]]
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
76 define 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]]
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
107 define 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]]
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
139 define 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]]
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
164 define 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]]
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
188 define <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]]
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
206 define <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]]
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
226 define 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]]
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
256 define 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]]
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
290 define 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]]
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
324 define i32 @n9(i64 %data, i32 %nbits) {
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]]
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
355 define i32 @n10(i64 %data, i32 %nbits) {
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]]
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
386 define i32 @n11(i64 %data, i32 %nbits1, i32 %nbits2) {
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]]
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
417 define i32 @n12(i64 %data, i32 %nbits1, i32 %nbits2) {
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]]
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
452 define i32 @n13(i64 %data, i32 %nbits) {
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]]
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
482 define 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]]
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
514 define i32 @n14(i64 %data, i32 %nbits) {
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]]
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
544 define 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]]
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