[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / narrow-math.ll
blob8caf93d690b500449ee19f7702a5c72300479b2a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 declare i32 @callee()
6 declare void @use(i64)
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]]
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
24 ; Negative test
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]]
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
43 ; Negative test
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]]
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
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]]
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
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]]
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
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]]
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
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
136   ret i64 %add
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
151   ret i64 %zext
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
167   ret i64 %add
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
182   ret i64 %zext
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
195   ret i64 %add
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
212   ret i64 %add
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>
225   ret <2 x i64> %add
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>
238   ret <2 x i64> %add
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
251   ret i64 %add
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>
264   ret <2 x i64> %add
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>
277   ret <2 x i64> %add
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>
290   ret <2 x i64> %add
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
303   ret i64 %add
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>
316   ret <2 x i64> %add
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>
329   ret <2 x i64> %add
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
342   ret i64 %mul
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>
355   ret <2 x i64> %mul
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>
368   ret <2 x i64> %mul
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>
381   ret <2 x i64> %mul
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
394   ret i64 %mul
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>
407   ret <2 x i64> %mul
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>
420   ret <2 x i64> %mul
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
433   ret i64 %mul
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>
446   ret <2 x i64> %mul
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>
459   ret <2 x i64> %mul
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
475   ret i64 %add
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
491   ret i64 %add
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
507   ret i64 %sub
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
523   ret i64 %sub
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
536   ret i64 %sub
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
549   ret <2 x i64> %sub
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
562   ret i64 %sub
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
575   ret <2 x i64> %sub
578 ; Negative test. Both have the same range so we can't guarantee the subtract
579 ; won't wrap.
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
594   ret i64 %sub
597 ; Negative test. LHS is large positive 32-bit number. Range of callee can
598 ; cause overflow.
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
609   ret i64 %sub
612 ; Negative test. LHS is large negative 32-bit number. Range of callee can
613 ; cause overflow.
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
624   ret i64 %sub
627 !0 = !{ i32 0, i32 2000 }
628 !1 = !{ i32 -2000, i32 0 }
629 !2 = !{ i32 -512, i32 -255 }
630 !3 = !{ i32 -128, i32 0 }