• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4declare i32 @callee()
5
6declare void @use(i64)
7
8define 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]]
15;
16  %B = ashr i32 %A, 7
17  %C = ashr i32 %A, 9
18  %D = sext i32 %B to i64
19  %E = sext i32 %C to i64
20  %F = add i64 %D, %E
21  ret i64 %F
22}
23
24; Negative test
25
26define 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]]
34;
35  %B = ashr i32 %A, 7
36  %C = lshr i32 %A, 9
37  %D = sext i32 %B to i64
38  %E = zext i32 %C to i64
39  %F = add i64 %D, %E
40  ret i64 %F
41}
42
43; Negative test
44
45define 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]]
53;
54  %B = ashr i16 %A, 7
55  %C = ashr i32 %x, 9
56  %D = sext i16 %B to i64
57  %E = sext i32 %C to i64
58  %F = add i64 %D, %E
59  ret i64 %F
60}
61
62define 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]]
71;
72  %B = ashr i32 %A, 7
73  %C = ashr i32 %A, 9
74  %D = sext i32 %B to i64
75  call void @use(i64 %D)
76  %E = sext i32 %C to i64
77  %F = add i64 %D, %E
78  ret i64 %F
79}
80
81define 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]]
90;
91  %B = ashr i32 %A, 7
92  %C = ashr i32 %A, 9
93  %D = sext i32 %B to i64
94  %E = sext i32 %C to i64
95  call void @use(i64 %E)
96  %F = add i64 %D, %E
97  ret i64 %F
98}
99
100; Negative test - if both extends have extra uses, we need an extra instruction.
101
102define 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]]
112;
113  %B = ashr i32 %A, 7
114  %C = ashr i32 %A, 9
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)
119  %F = add i64 %D, %E
120  ret i64 %F
121}
122
123define i64 @test1(i32 %V) {
124; CHECK-LABEL: @test1(
125; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0:!range !.*]]
126; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
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]]
130;
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
136  ret i64 %add
137}
138
139define i64 @test2(i32 %V) {
140; CHECK-LABEL: @test2(
141; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0]]
142; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
143; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[CALL1]], [[CALL2]]
144; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[ADD]] to i64
145; CHECK-NEXT:    ret i64 [[ZEXT]]
146;
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
151  ret i64 %zext
152}
153
154define i64 @test3(i32 %V) {
155; CHECK-LABEL: @test3(
156; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0]]
157; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
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]]
161;
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
167  ret i64 %add
168}
169
170define i64 @test4(i32 %V) {
171; CHECK-LABEL: @test4(
172; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0]]
173; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
174; CHECK-NEXT:    [[ADD:%.*]] = mul nuw nsw i32 [[CALL1]], [[CALL2]]
175; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[ADD]] to i64
176; CHECK-NEXT:    ret i64 [[ZEXT]]
177;
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
182  ret i64 %zext
183}
184
185define 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]]
191;
192  %ashr = ashr i32 %V, 1
193  %sext = sext i32 %ashr to i64
194  %add = add i64 %sext, 1073741823
195  ret i64 %add
196}
197
198; Negative test - extra use means we'd have more instructions than we started with.
199
200define 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]]
207;
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
212  ret i64 %add
213}
214
215define <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]]
221;
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>
225  ret <2 x i64> %add
226}
227
228define <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]]
234;
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>
238  ret <2 x i64> %add
239}
240
241define 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]]
247;
248  %ashr = ashr i32 %V, 1
249  %sext = sext i32 %ashr to i64
250  %add = add i64 %sext, -1073741824
251  ret i64 %add
252}
253
254define <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]]
260;
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>
264  ret <2 x i64> %add
265}
266
267define <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]]
273;
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>
277  ret <2 x i64> %add
278}
279
280define <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]]
286;
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>
290  ret <2 x i64> %add
291}
292
293define 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]]
299;
300  %lshr = lshr i32 %V, 1
301  %zext = zext i32 %lshr to i64
302  %add = add i64 %zext, 2147483647
303  ret i64 %add
304}
305
306define <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]]
312;
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>
316  ret <2 x i64> %add
317}
318
319define <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]]
325;
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>
329  ret <2 x i64> %add
330}
331
332define 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]]
338;
339  %ashr = ashr i32 %V, 16
340  %sext = sext i32 %ashr to i64
341  %mul = mul i64 %sext, 32767
342  ret i64 %mul
343}
344
345define <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]]
351;
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>
355  ret <2 x i64> %mul
356}
357
358define <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]]
364;
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>
368  ret <2 x i64> %mul
369}
370
371define <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]]
377;
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>
381  ret <2 x i64> %mul
382}
383
384define 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]]
390;
391  %ashr = ashr i32 %V, 16
392  %sext = sext i32 %ashr to i64
393  %mul = mul i64 %sext, -32767
394  ret i64 %mul
395}
396
397define <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]]
403;
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>
407  ret <2 x i64> %mul
408}
409
410define <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]]
416;
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>
420  ret <2 x i64> %mul
421}
422
423define 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]]
429;
430  %lshr = lshr i32 %V, 16
431  %zext = zext i32 %lshr to i64
432  %mul = mul i64 %zext, 65535
433  ret i64 %mul
434}
435
436define <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]]
442;
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>
446  ret <2 x i64> %mul
447}
448
449define <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]]
455;
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>
459  ret <2 x i64> %mul
460}
461
462define i64 @test11(i32 %V) {
463; CHECK-LABEL: @test11(
464; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG1:!range !.*]]
465; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG1]]
466; CHECK-NEXT:    [[NARROW:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
467; CHECK-NEXT:    [[ADD:%.*]] = sext i32 [[NARROW]] to i64
468; CHECK-NEXT:    ret i64 [[ADD]]
469;
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
475  ret i64 %add
476}
477
478define i64 @test12(i32 %V) {
479; CHECK-LABEL: @test12(
480; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG1]]
481; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG1]]
482; CHECK-NEXT:    [[NARROW:%.*]] = mul nsw i32 [[CALL1]], [[CALL2]]
483; CHECK-NEXT:    [[ADD:%.*]] = zext i32 [[NARROW]] to i64
484; CHECK-NEXT:    ret i64 [[ADD]]
485;
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
491  ret i64 %add
492}
493
494define i64 @test13(i32 %V) {
495; CHECK-LABEL: @test13(
496; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG2:!range !.*]]
497; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG3:!range !.*]]
498; CHECK-NEXT:    [[NARROW:%.*]] = sub nsw i32 [[CALL1]], [[CALL2]]
499; CHECK-NEXT:    [[SUB:%.*]] = sext i32 [[NARROW]] to i64
500; CHECK-NEXT:    ret i64 [[SUB]]
501;
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
507  ret i64 %sub
508}
509
510define i64 @test14(i32 %V) {
511; CHECK-LABEL: @test14(
512; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG2]]
513; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
514; CHECK-NEXT:    [[NARROW:%.*]] = sub nuw nsw i32 [[CALL1]], [[CALL2]]
515; CHECK-NEXT:    [[SUB:%.*]] = zext i32 [[NARROW]] to i64
516; CHECK-NEXT:    ret i64 [[SUB]]
517;
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
523  ret i64 %sub
524}
525
526define i64 @test15(i32 %V) {
527; CHECK-LABEL: @test15(
528; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
529; CHECK-NEXT:    [[NARROW:%.*]] = sub nsw i32 8, [[ASHR]]
530; CHECK-NEXT:    [[SUB:%.*]] = sext i32 [[NARROW]] to i64
531; CHECK-NEXT:    ret i64 [[SUB]]
532;
533  %ashr = ashr i32 %V, 1
534  %sext = sext i32 %ashr to i64
535  %sub = sub i64 8, %sext
536  ret i64 %sub
537}
538
539define <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:    [[NARROW:%.*]] = sub nsw <2 x i32> <i32 8, i32 8>, [[ASHR]]
543; CHECK-NEXT:    [[SUB:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
544; CHECK-NEXT:    ret <2 x i64> [[SUB]]
545;
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
549  ret <2 x i64> %sub
550}
551
552define i64 @test16(i32 %V) {
553; CHECK-LABEL: @test16(
554; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1
555; CHECK-NEXT:    [[NARROW:%.*]] = sub nuw i32 -2, [[LSHR]]
556; CHECK-NEXT:    [[SUB:%.*]] = zext i32 [[NARROW]] to i64
557; CHECK-NEXT:    ret i64 [[SUB]]
558;
559  %lshr = lshr i32 %V, 1
560  %zext = zext i32 %lshr to i64
561  %sub = sub i64 4294967294, %zext
562  ret i64 %sub
563}
564
565define <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:    [[NARROW:%.*]] = sub nuw <2 x i32> <i32 -2, i32 -2>, [[LSHR]]
569; CHECK-NEXT:    [[SUB:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
570; CHECK-NEXT:    ret <2 x i64> [[SUB]]
571;
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
575  ret <2 x i64> %sub
576}
577
578; Negative test. Both have the same range so we can't guarantee the subtract
579; won't wrap.
580define i64 @test17(i32 %V) {
581; CHECK-LABEL: @test17(
582; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0]]
583; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @callee(), [[RNG0]]
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]]
588;
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
594  ret i64 %sub
595}
596
597; Negative test. LHS is large positive 32-bit number. Range of callee can
598; cause overflow.
599define i64 @test18(i32 %V) {
600; CHECK-LABEL: @test18(
601; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG1]]
602; CHECK-NEXT:    [[SEXT1:%.*]] = sext i32 [[CALL1]] to i64
603; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i64 2147481648, [[SEXT1]]
604; CHECK-NEXT:    ret i64 [[SUB]]
605;
606  %call1 = call i32 @callee(), !range !1
607  %sext1 = sext i32 %call1 to i64
608  %sub = sub i64 2147481648, %sext1
609  ret i64 %sub
610}
611
612; Negative test. LHS is large negative 32-bit number. Range of callee can
613; cause overflow.
614define i64 @test19(i32 %V) {
615; CHECK-LABEL: @test19(
616; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @callee(), [[RNG0]]
617; CHECK-NEXT:    [[SEXT1:%.*]] = zext i32 [[CALL1]] to i64
618; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i64 -2147481648, [[SEXT1]]
619; CHECK-NEXT:    ret i64 [[SUB]]
620;
621  %call1 = call i32 @callee(), !range !0
622  %sext1 = sext i32 %call1 to i64
623  %sub = sub i64 -2147481648, %sext1
624  ret i64 %sub
625}
626
627!0 = !{ i32 0, i32 2000 }
628!1 = !{ i32 -2000, i32 0 }
629!2 = !{ i32 -512, i32 -255 }
630!3 = !{ i32 -128, i32 0 }
631