1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
8 define i64 @sext_sext_add(i32 %A) {
9 ; CHECK-LABEL: @sext_sext_add(
10 ; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7
11 ; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 9
12 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]
13 ; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i64
14 ; CHECK-NEXT: ret i64 [[F]]
18 %D = sext i32 %B to i64
19 %E = sext i32 %C to i64
26 define i64 @sext_zext_add_mismatched_exts(i32 %A) {
27 ; CHECK-LABEL: @sext_zext_add_mismatched_exts(
28 ; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7
29 ; CHECK-NEXT: [[C:%.*]] = lshr i32 [[A]], 9
30 ; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i64
31 ; CHECK-NEXT: [[E:%.*]] = zext i32 [[C]] to i64
32 ; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]
33 ; CHECK-NEXT: ret i64 [[F]]
37 %D = sext i32 %B to i64
38 %E = zext i32 %C to i64
45 define i64 @sext_sext_add_mismatched_types(i16 %A, i32 %x) {
46 ; CHECK-LABEL: @sext_sext_add_mismatched_types(
47 ; CHECK-NEXT: [[B:%.*]] = ashr i16 [[A:%.*]], 7
48 ; CHECK-NEXT: [[C:%.*]] = ashr i32 [[X:%.*]], 9
49 ; CHECK-NEXT: [[D:%.*]] = sext i16 [[B]] to i64
50 ; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i64
51 ; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]
52 ; CHECK-NEXT: ret i64 [[F]]
56 %D = sext i16 %B to i64
57 %E = sext i32 %C to i64
62 define i64 @sext_sext_add_extra_use1(i32 %A) {
63 ; CHECK-LABEL: @sext_sext_add_extra_use1(
64 ; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7
65 ; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 9
66 ; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i64
67 ; CHECK-NEXT: call void @use(i64 [[D]])
68 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]
69 ; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i64
70 ; CHECK-NEXT: ret i64 [[F]]
74 %D = sext i32 %B to i64
75 call void @use(i64 %D)
76 %E = sext i32 %C to i64
81 define i64 @sext_sext_add_extra_use2(i32 %A) {
82 ; CHECK-LABEL: @sext_sext_add_extra_use2(
83 ; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7
84 ; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 9
85 ; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i64
86 ; CHECK-NEXT: call void @use(i64 [[E]])
87 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]
88 ; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i64
89 ; CHECK-NEXT: ret i64 [[F]]
93 %D = sext i32 %B to i64
94 %E = sext i32 %C to i64
95 call void @use(i64 %E)
100 ; Negative test - if both extends have extra uses, we need an extra instruction.
102 define i64 @sext_sext_add_extra_use3(i32 %A) {
103 ; CHECK-LABEL: @sext_sext_add_extra_use3(
104 ; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7
105 ; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 9
106 ; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i64
107 ; CHECK-NEXT: call void @use(i64 [[D]])
108 ; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i64
109 ; CHECK-NEXT: call void @use(i64 [[E]])
110 ; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]
111 ; CHECK-NEXT: ret i64 [[F]]
115 %D = sext i32 %B to i64
116 call void @use(i64 %D)
117 %E = sext i32 %C to i64
118 call void @use(i64 %E)
123 define i64 @test1(i32 %V) {
124 ; CHECK-LABEL: @test1(
125 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
126 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
127 ; CHECK-NEXT: [[NARROW:%.*]] = add nuw nsw i32 [[CALL1]], [[CALL2]]
128 ; CHECK-NEXT: [[ADD:%.*]] = zext i32 [[NARROW]] to i64
129 ; CHECK-NEXT: ret i64 [[ADD]]
131 %call1 = call i32 @callee(), !range !0
132 %call2 = call i32 @callee(), !range !0
133 %zext1 = sext i32 %call1 to i64
134 %zext2 = sext i32 %call2 to i64
135 %add = add i64 %zext1, %zext2
139 define i64 @test2(i32 %V) {
140 ; CHECK-LABEL: @test2(
141 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
142 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
143 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[CALL1]], [[CALL2]]
144 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[ADD]] to i64
145 ; CHECK-NEXT: ret i64 [[TMP1]]
147 %call1 = call i32 @callee(), !range !0
148 %call2 = call i32 @callee(), !range !0
149 %add = add i32 %call1, %call2
150 %zext = sext i32 %add to i64
154 define i64 @test3(i32 %V) {
155 ; CHECK-LABEL: @test3(
156 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
157 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
158 ; CHECK-NEXT: [[NARROW:%.*]] = mul nuw nsw i32 [[CALL1]], [[CALL2]]
159 ; CHECK-NEXT: [[ADD:%.*]] = zext i32 [[NARROW]] to i64
160 ; CHECK-NEXT: ret i64 [[ADD]]
162 %call1 = call i32 @callee(), !range !0
163 %call2 = call i32 @callee(), !range !0
164 %zext1 = sext i32 %call1 to i64
165 %zext2 = sext i32 %call2 to i64
166 %add = mul i64 %zext1, %zext2
170 define i64 @test4(i32 %V) {
171 ; CHECK-LABEL: @test4(
172 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
173 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
174 ; CHECK-NEXT: [[ADD:%.*]] = mul nuw nsw i32 [[CALL1]], [[CALL2]]
175 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[ADD]] to i64
176 ; CHECK-NEXT: ret i64 [[TMP1]]
178 %call1 = call i32 @callee(), !range !0
179 %call2 = call i32 @callee(), !range !0
180 %add = mul i32 %call1, %call2
181 %zext = sext i32 %add to i64
185 define i64 @test5(i32 %V) {
186 ; CHECK-LABEL: @test5(
187 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
188 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[ASHR]], 1073741823
189 ; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64
190 ; CHECK-NEXT: ret i64 [[ADD]]
192 %ashr = ashr i32 %V, 1
193 %sext = sext i32 %ashr to i64
194 %add = add i64 %sext, 1073741823
198 ; Negative test - extra use means we'd have more instructions than we started with.
200 define i64 @sext_add_constant_extra_use(i32 %V) {
201 ; CHECK-LABEL: @sext_add_constant_extra_use(
202 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
203 ; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[ASHR]] to i64
204 ; CHECK-NEXT: call void @use(i64 [[SEXT]])
205 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SEXT]], 1073741823
206 ; CHECK-NEXT: ret i64 [[ADD]]
208 %ashr = ashr i32 %V, 1
209 %sext = sext i32 %ashr to i64
210 call void @use(i64 %sext)
211 %add = add i64 %sext, 1073741823
215 define <2 x i64> @test5_splat(<2 x i32> %V) {
216 ; CHECK-LABEL: @test5_splat(
217 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
218 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 1073741823, i32 1073741823>
219 ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
220 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
222 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
223 %sext = sext <2 x i32> %ashr to <2 x i64>
224 %add = add <2 x i64> %sext, <i64 1073741823, i64 1073741823>
228 define <2 x i64> @test5_vec(<2 x i32> %V) {
229 ; CHECK-LABEL: @test5_vec(
230 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
231 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 1, i32 2>
232 ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
233 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
235 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
236 %sext = sext <2 x i32> %ashr to <2 x i64>
237 %add = add <2 x i64> %sext, <i64 1, i64 2>
241 define i64 @test6(i32 %V) {
242 ; CHECK-LABEL: @test6(
243 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
244 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[ASHR]], -1073741824
245 ; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64
246 ; CHECK-NEXT: ret i64 [[ADD]]
248 %ashr = ashr i32 %V, 1
249 %sext = sext i32 %ashr to i64
250 %add = add i64 %sext, -1073741824
254 define <2 x i64> @test6_splat(<2 x i32> %V) {
255 ; CHECK-LABEL: @test6_splat(
256 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
257 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 -1073741824, i32 -1073741824>
258 ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
259 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
261 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
262 %sext = sext <2 x i32> %ashr to <2 x i64>
263 %add = add <2 x i64> %sext, <i64 -1073741824, i64 -1073741824>
267 define <2 x i64> @test6_vec(<2 x i32> %V) {
268 ; CHECK-LABEL: @test6_vec(
269 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
270 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 -1, i32 -2>
271 ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
272 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
274 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
275 %sext = sext <2 x i32> %ashr to <2 x i64>
276 %add = add <2 x i64> %sext, <i64 -1, i64 -2>
280 define <2 x i64> @test6_vec2(<2 x i32> %V) {
281 ; CHECK-LABEL: @test6_vec2(
282 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
283 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 -1, i32 1>
284 ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
285 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
287 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
288 %sext = sext <2 x i32> %ashr to <2 x i64>
289 %add = add <2 x i64> %sext, <i64 -1, i64 1>
293 define i64 @test7(i32 %V) {
294 ; CHECK-LABEL: @test7(
295 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1
296 ; CHECK-NEXT: [[NARROW:%.*]] = add nuw i32 [[LSHR]], 2147483647
297 ; CHECK-NEXT: [[ADD:%.*]] = zext i32 [[NARROW]] to i64
298 ; CHECK-NEXT: ret i64 [[ADD]]
300 %lshr = lshr i32 %V, 1
301 %zext = zext i32 %lshr to i64
302 %add = add i64 %zext, 2147483647
306 define <2 x i64> @test7_splat(<2 x i32> %V) {
307 ; CHECK-LABEL: @test7_splat(
308 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 1, i32 1>
309 ; CHECK-NEXT: [[NARROW:%.*]] = add nuw <2 x i32> [[LSHR]], <i32 2147483647, i32 2147483647>
310 ; CHECK-NEXT: [[ADD:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
311 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
313 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>
314 %zext = zext <2 x i32> %lshr to <2 x i64>
315 %add = add <2 x i64> %zext, <i64 2147483647, i64 2147483647>
319 define <2 x i64> @test7_vec(<2 x i32> %V) {
320 ; CHECK-LABEL: @test7_vec(
321 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 1, i32 1>
322 ; CHECK-NEXT: [[NARROW:%.*]] = add nuw <2 x i32> [[LSHR]], <i32 1, i32 2>
323 ; CHECK-NEXT: [[ADD:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
324 ; CHECK-NEXT: ret <2 x i64> [[ADD]]
326 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>
327 %zext = zext <2 x i32> %lshr to <2 x i64>
328 %add = add <2 x i64> %zext, <i64 1, i64 2>
332 define i64 @test8(i32 %V) {
333 ; CHECK-LABEL: @test8(
334 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 16
335 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[ASHR]], 32767
336 ; CHECK-NEXT: [[MUL:%.*]] = sext i32 [[NARROW]] to i64
337 ; CHECK-NEXT: ret i64 [[MUL]]
339 %ashr = ashr i32 %V, 16
340 %sext = sext i32 %ashr to i64
341 %mul = mul i64 %sext, 32767
345 define <2 x i64> @test8_splat(<2 x i32> %V) {
346 ; CHECK-LABEL: @test8_splat(
347 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 16, i32 16>
348 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 32767, i32 32767>
349 ; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
350 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
352 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>
353 %sext = sext <2 x i32> %ashr to <2 x i64>
354 %mul = mul <2 x i64> %sext, <i64 32767, i64 32767>
358 define <2 x i64> @test8_vec(<2 x i32> %V) {
359 ; CHECK-LABEL: @test8_vec(
360 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 16, i32 16>
361 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 32767, i32 16384>
362 ; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
363 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
365 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>
366 %sext = sext <2 x i32> %ashr to <2 x i64>
367 %mul = mul <2 x i64> %sext, <i64 32767, i64 16384>
371 define <2 x i64> @test8_vec2(<2 x i32> %V) {
372 ; CHECK-LABEL: @test8_vec2(
373 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 16, i32 16>
374 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 32767, i32 -32767>
375 ; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
376 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
378 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>
379 %sext = sext <2 x i32> %ashr to <2 x i64>
380 %mul = mul <2 x i64> %sext, <i64 32767, i64 -32767>
384 define i64 @test9(i32 %V) {
385 ; CHECK-LABEL: @test9(
386 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 16
387 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[ASHR]], -32767
388 ; CHECK-NEXT: [[MUL:%.*]] = sext i32 [[NARROW]] to i64
389 ; CHECK-NEXT: ret i64 [[MUL]]
391 %ashr = ashr i32 %V, 16
392 %sext = sext i32 %ashr to i64
393 %mul = mul i64 %sext, -32767
397 define <2 x i64> @test9_splat(<2 x i32> %V) {
398 ; CHECK-LABEL: @test9_splat(
399 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 16, i32 16>
400 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 -32767, i32 -32767>
401 ; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
402 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
404 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>
405 %sext = sext <2 x i32> %ashr to <2 x i64>
406 %mul = mul <2 x i64> %sext, <i64 -32767, i64 -32767>
410 define <2 x i64> @test9_vec(<2 x i32> %V) {
411 ; CHECK-LABEL: @test9_vec(
412 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 16, i32 16>
413 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 -32767, i32 -10>
414 ; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
415 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
417 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>
418 %sext = sext <2 x i32> %ashr to <2 x i64>
419 %mul = mul <2 x i64> %sext, <i64 -32767, i64 -10>
423 define i64 @test10(i32 %V) {
424 ; CHECK-LABEL: @test10(
425 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 16
426 ; CHECK-NEXT: [[NARROW:%.*]] = mul nuw i32 [[LSHR]], 65535
427 ; CHECK-NEXT: [[MUL:%.*]] = zext i32 [[NARROW]] to i64
428 ; CHECK-NEXT: ret i64 [[MUL]]
430 %lshr = lshr i32 %V, 16
431 %zext = zext i32 %lshr to i64
432 %mul = mul i64 %zext, 65535
436 define <2 x i64> @test10_splat(<2 x i32> %V) {
437 ; CHECK-LABEL: @test10_splat(
438 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 16, i32 16>
439 ; CHECK-NEXT: [[NARROW:%.*]] = mul nuw <2 x i32> [[LSHR]], <i32 65535, i32 65535>
440 ; CHECK-NEXT: [[MUL:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
441 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
443 %lshr = lshr <2 x i32> %V, <i32 16, i32 16>
444 %zext = zext <2 x i32> %lshr to <2 x i64>
445 %mul = mul <2 x i64> %zext, <i64 65535, i64 65535>
449 define <2 x i64> @test10_vec(<2 x i32> %V) {
450 ; CHECK-LABEL: @test10_vec(
451 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 16, i32 16>
452 ; CHECK-NEXT: [[NARROW:%.*]] = mul nuw <2 x i32> [[LSHR]], <i32 65535, i32 2>
453 ; CHECK-NEXT: [[MUL:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
454 ; CHECK-NEXT: ret <2 x i64> [[MUL]]
456 %lshr = lshr <2 x i32> %V, <i32 16, i32 16>
457 %zext = zext <2 x i32> %lshr to <2 x i64>
458 %mul = mul <2 x i64> %zext, <i64 65535, i64 2>
462 define i64 @test11(i32 %V) {
463 ; CHECK-LABEL: @test11(
464 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !1
465 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !1
466 ; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
467 ; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64
468 ; CHECK-NEXT: ret i64 [[ADD]]
470 %call1 = call i32 @callee(), !range !1
471 %call2 = call i32 @callee(), !range !1
472 %sext1 = sext i32 %call1 to i64
473 %sext2 = sext i32 %call2 to i64
474 %add = add i64 %sext1, %sext2
478 define i64 @test12(i32 %V) {
479 ; CHECK-LABEL: @test12(
480 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !1
481 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !1
482 ; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[CALL1]], [[CALL2]]
483 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[NARROW]] to i64
484 ; CHECK-NEXT: ret i64 [[TMP1]]
486 %call1 = call i32 @callee(), !range !1
487 %call2 = call i32 @callee(), !range !1
488 %sext1 = sext i32 %call1 to i64
489 %sext2 = sext i32 %call2 to i64
490 %add = mul i64 %sext1, %sext2
494 define i64 @test13(i32 %V) {
495 ; CHECK-LABEL: @test13(
496 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !2
497 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !3
498 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw i32 [[CALL1]], [[CALL2]]
499 ; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[SUBCONV]] to i64
500 ; CHECK-NEXT: ret i64 [[SUB]]
502 %call1 = call i32 @callee(), !range !2
503 %call2 = call i32 @callee(), !range !3
504 %sext1 = sext i32 %call1 to i64
505 %sext2 = sext i32 %call2 to i64
506 %sub = sub i64 %sext1, %sext2
510 define i64 @test14(i32 %V) {
511 ; CHECK-LABEL: @test14(
512 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !2
513 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
514 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw nsw i32 [[CALL1]], [[CALL2]]
515 ; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[SUBCONV]] to i64
516 ; CHECK-NEXT: ret i64 [[SUB]]
518 %call1 = call i32 @callee(), !range !2
519 %call2 = call i32 @callee(), !range !0
520 %zext1 = zext i32 %call1 to i64
521 %zext2 = zext i32 %call2 to i64
522 %sub = sub i64 %zext1, %zext2
526 define i64 @test15(i32 %V) {
527 ; CHECK-LABEL: @test15(
528 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
529 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw i32 8, [[ASHR]]
530 ; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[SUBCONV]] to i64
531 ; CHECK-NEXT: ret i64 [[SUB]]
533 %ashr = ashr i32 %V, 1
534 %sext = sext i32 %ashr to i64
535 %sub = sub i64 8, %sext
539 define <2 x i64> @test15vec(<2 x i32> %V) {
540 ; CHECK-LABEL: @test15vec(
541 ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
542 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw <2 x i32> <i32 8, i32 8>, [[ASHR]]
543 ; CHECK-NEXT: [[SUB:%.*]] = sext <2 x i32> [[SUBCONV]] to <2 x i64>
544 ; CHECK-NEXT: ret <2 x i64> [[SUB]]
546 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>
547 %sext = sext <2 x i32> %ashr to <2 x i64>
548 %sub = sub <2 x i64> <i64 8, i64 8>, %sext
552 define i64 @test16(i32 %V) {
553 ; CHECK-LABEL: @test16(
554 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1
555 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw i32 -2, [[LSHR]]
556 ; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[SUBCONV]] to i64
557 ; CHECK-NEXT: ret i64 [[SUB]]
559 %lshr = lshr i32 %V, 1
560 %zext = zext i32 %lshr to i64
561 %sub = sub i64 4294967294, %zext
565 define <2 x i64> @test16vec(<2 x i32> %V) {
566 ; CHECK-LABEL: @test16vec(
567 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 1, i32 1>
568 ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw <2 x i32> <i32 -2, i32 -2>, [[LSHR]]
569 ; CHECK-NEXT: [[SUB:%.*]] = zext <2 x i32> [[SUBCONV]] to <2 x i64>
570 ; CHECK-NEXT: ret <2 x i64> [[SUB]]
572 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>
573 %zext = zext <2 x i32> %lshr to <2 x i64>
574 %sub = sub <2 x i64> <i64 4294967294, i64 4294967294>, %zext
578 ; Negative test. Both have the same range so we can't guarantee the subtract
580 define i64 @test17(i32 %V) {
581 ; CHECK-LABEL: @test17(
582 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
583 ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
584 ; CHECK-NEXT: [[SEXT1:%.*]] = zext i32 [[CALL1]] to i64
585 ; CHECK-NEXT: [[SEXT2:%.*]] = zext i32 [[CALL2]] to i64
586 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
587 ; CHECK-NEXT: ret i64 [[SUB]]
589 %call1 = call i32 @callee(), !range !0
590 %call2 = call i32 @callee(), !range !0
591 %sext1 = zext i32 %call1 to i64
592 %sext2 = zext i32 %call2 to i64
593 %sub = sub i64 %sext1, %sext2
597 ; Negative test. LHS is large positive 32-bit number. Range of callee can
599 define i64 @test18(i32 %V) {
600 ; CHECK-LABEL: @test18(
601 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !1
602 ; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[CALL1]] to i64
603 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 2147481648, [[SEXT1]]
604 ; CHECK-NEXT: ret i64 [[SUB]]
606 %call1 = call i32 @callee(), !range !1
607 %sext1 = sext i32 %call1 to i64
608 %sub = sub i64 2147481648, %sext1
612 ; Negative test. LHS is large negative 32-bit number. Range of callee can
614 define i64 @test19(i32 %V) {
615 ; CHECK-LABEL: @test19(
616 ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
617 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[CALL1]] to i64
618 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i64 -2147481648, [[TMP1]]
619 ; CHECK-NEXT: ret i64 [[SUB]]
621 %call1 = call i32 @callee(), !range !0
622 %sext1 = sext i32 %call1 to i64
623 %sub = sub i64 -2147481648, %sext1
627 !0 = !{ i32 0, i32 2000 }
628 !1 = !{ i32 -2000, i32 0 }
629 !2 = !{ i32 -512, i32 -255 }
630 !3 = !{ i32 -128, i32 0 }