1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X32
3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux | FileCheck %s --check-prefixes=X64,X64-LINUX
4 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-win32 | FileCheck %s --check-prefixes=X64,X64-WIN32
6 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32)
7 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32)
9 ; The immediate can be encoded in a smaller way if the
10 ; instruction is a sub instead of an add.
11 define i32 @test1(i32 inreg %a) nounwind {
13 ; X32: # %bb.0: # %entry
14 ; X32-NEXT: subl $-128, %eax
17 ; X64-LINUX-LABEL: test1:
18 ; X64-LINUX: # %bb.0: # %entry
19 ; X64-LINUX-NEXT: movl %edi, %eax
20 ; X64-LINUX-NEXT: subl $-128, %eax
21 ; X64-LINUX-NEXT: retq
23 ; X64-WIN32-LABEL: test1:
24 ; X64-WIN32: # %bb.0: # %entry
25 ; X64-WIN32-NEXT: movl %ecx, %eax
26 ; X64-WIN32-NEXT: subl $-128, %eax
27 ; X64-WIN32-NEXT: retq
32 define i64 @test2(i64 inreg %a) nounwind {
34 ; X32: # %bb.0: # %entry
35 ; X32-NEXT: addl $-2147483648, %eax # imm = 0x80000000
36 ; X32-NEXT: adcl $0, %edx
39 ; X64-LINUX-LABEL: test2:
40 ; X64-LINUX: # %bb.0: # %entry
41 ; X64-LINUX-NEXT: movq %rdi, %rax
42 ; X64-LINUX-NEXT: subq $-2147483648, %rax # imm = 0x80000000
43 ; X64-LINUX-NEXT: retq
45 ; X64-WIN32-LABEL: test2:
46 ; X64-WIN32: # %bb.0: # %entry
47 ; X64-WIN32-NEXT: movq %rcx, %rax
48 ; X64-WIN32-NEXT: subq $-2147483648, %rax # imm = 0x80000000
49 ; X64-WIN32-NEXT: retq
51 %b = add i64 %a, 2147483648
54 define i64 @test3(i64 inreg %a) nounwind {
56 ; X32: # %bb.0: # %entry
57 ; X32-NEXT: addl $128, %eax
58 ; X32-NEXT: adcl $0, %edx
61 ; X64-LINUX-LABEL: test3:
62 ; X64-LINUX: # %bb.0: # %entry
63 ; X64-LINUX-NEXT: movq %rdi, %rax
64 ; X64-LINUX-NEXT: subq $-128, %rax
65 ; X64-LINUX-NEXT: retq
67 ; X64-WIN32-LABEL: test3:
68 ; X64-WIN32: # %bb.0: # %entry
69 ; X64-WIN32-NEXT: movq %rcx, %rax
70 ; X64-WIN32-NEXT: subq $-128, %rax
71 ; X64-WIN32-NEXT: retq
77 define i1 @test4(i32 %v1, i32 %v2, i32* %X) nounwind {
79 ; X32: # %bb.0: # %entry
80 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
81 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax
82 ; X32-NEXT: jo .LBB3_2
83 ; X32-NEXT: # %bb.1: # %normal
84 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
85 ; X32-NEXT: movl $0, (%eax)
86 ; X32-NEXT: .LBB3_2: # %overflow
87 ; X32-NEXT: xorl %eax, %eax
90 ; X64-LINUX-LABEL: test4:
91 ; X64-LINUX: # %bb.0: # %entry
92 ; X64-LINUX-NEXT: addl %esi, %edi
93 ; X64-LINUX-NEXT: jo .LBB3_2
94 ; X64-LINUX-NEXT: # %bb.1: # %normal
95 ; X64-LINUX-NEXT: movl $0, (%rdx)
96 ; X64-LINUX-NEXT: .LBB3_2: # %overflow
97 ; X64-LINUX-NEXT: xorl %eax, %eax
98 ; X64-LINUX-NEXT: retq
100 ; X64-WIN32-LABEL: test4:
101 ; X64-WIN32: # %bb.0: # %entry
102 ; X64-WIN32-NEXT: addl %edx, %ecx
103 ; X64-WIN32-NEXT: jo .LBB3_2
104 ; X64-WIN32-NEXT: # %bb.1: # %normal
105 ; X64-WIN32-NEXT: movl $0, (%r8)
106 ; X64-WIN32-NEXT: .LBB3_2: # %overflow
107 ; X64-WIN32-NEXT: xorl %eax, %eax
108 ; X64-WIN32-NEXT: retq
110 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
111 %sum = extractvalue {i32, i1} %t, 0
112 %obit = extractvalue {i32, i1} %t, 1
113 br i1 %obit, label %overflow, label %normal
123 define i1 @test5(i32 %v1, i32 %v2, i32* %X) nounwind {
125 ; X32: # %bb.0: # %entry
126 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
127 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax
128 ; X32-NEXT: jb .LBB4_2
129 ; X32-NEXT: # %bb.1: # %normal
130 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
131 ; X32-NEXT: movl $0, (%eax)
132 ; X32-NEXT: .LBB4_2: # %carry
133 ; X32-NEXT: xorl %eax, %eax
136 ; X64-LINUX-LABEL: test5:
137 ; X64-LINUX: # %bb.0: # %entry
138 ; X64-LINUX-NEXT: addl %esi, %edi
139 ; X64-LINUX-NEXT: jb .LBB4_2
140 ; X64-LINUX-NEXT: # %bb.1: # %normal
141 ; X64-LINUX-NEXT: movl $0, (%rdx)
142 ; X64-LINUX-NEXT: .LBB4_2: # %carry
143 ; X64-LINUX-NEXT: xorl %eax, %eax
144 ; X64-LINUX-NEXT: retq
146 ; X64-WIN32-LABEL: test5:
147 ; X64-WIN32: # %bb.0: # %entry
148 ; X64-WIN32-NEXT: addl %edx, %ecx
149 ; X64-WIN32-NEXT: jb .LBB4_2
150 ; X64-WIN32-NEXT: # %bb.1: # %normal
151 ; X64-WIN32-NEXT: movl $0, (%r8)
152 ; X64-WIN32-NEXT: .LBB4_2: # %carry
153 ; X64-WIN32-NEXT: xorl %eax, %eax
154 ; X64-WIN32-NEXT: retq
156 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
157 %sum = extractvalue {i32, i1} %t, 0
158 %obit = extractvalue {i32, i1} %t, 1
159 br i1 %obit, label %carry, label %normal
169 define i64 @test6(i64 %A, i32 %B) nounwind {
171 ; X32: # %bb.0: # %entry
172 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
173 ; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
174 ; X32-NEXT: addl {{[0-9]+}}(%esp), %edx
177 ; X64-LINUX-LABEL: test6:
178 ; X64-LINUX: # %bb.0: # %entry
179 ; X64-LINUX-NEXT: # kill: def $esi killed $esi def $rsi
180 ; X64-LINUX-NEXT: shlq $32, %rsi
181 ; X64-LINUX-NEXT: leaq (%rsi,%rdi), %rax
182 ; X64-LINUX-NEXT: retq
184 ; X64-WIN32-LABEL: test6:
185 ; X64-WIN32: # %bb.0: # %entry
186 ; X64-WIN32-NEXT: # kill: def $edx killed $edx def $rdx
187 ; X64-WIN32-NEXT: shlq $32, %rdx
188 ; X64-WIN32-NEXT: leaq (%rdx,%rcx), %rax
189 ; X64-WIN32-NEXT: retq
191 %tmp12 = zext i32 %B to i64
192 %tmp3 = shl i64 %tmp12, 32
193 %tmp5 = add i64 %tmp3, %A
197 define {i32, i1} @test7(i32 %v1, i32 %v2) nounwind {
199 ; X32: # %bb.0: # %entry
200 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
201 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax
205 ; X64-LINUX-LABEL: test7:
206 ; X64-LINUX: # %bb.0: # %entry
207 ; X64-LINUX-NEXT: movl %edi, %eax
208 ; X64-LINUX-NEXT: addl %esi, %eax
209 ; X64-LINUX-NEXT: setb %dl
210 ; X64-LINUX-NEXT: retq
212 ; X64-WIN32-LABEL: test7:
213 ; X64-WIN32: # %bb.0: # %entry
214 ; X64-WIN32-NEXT: movl %ecx, %eax
215 ; X64-WIN32-NEXT: addl %edx, %eax
216 ; X64-WIN32-NEXT: setb %dl
217 ; X64-WIN32-NEXT: retq
219 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
224 define {i64, i1} @test8(i64 %left, i64 %right) nounwind {
226 ; X32: # %bb.0: # %entry
227 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
228 ; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
229 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax
230 ; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx
234 ; X64-LINUX-LABEL: test8:
235 ; X64-LINUX: # %bb.0: # %entry
236 ; X64-LINUX-NEXT: movq %rdi, %rax
237 ; X64-LINUX-NEXT: addq %rsi, %rax
238 ; X64-LINUX-NEXT: setb %dl
239 ; X64-LINUX-NEXT: retq
241 ; X64-WIN32-LABEL: test8:
242 ; X64-WIN32: # %bb.0: # %entry
243 ; X64-WIN32-NEXT: movq %rcx, %rax
244 ; X64-WIN32-NEXT: addq %rdx, %rax
245 ; X64-WIN32-NEXT: setb %dl
246 ; X64-WIN32-NEXT: retq
248 %extleft = zext i64 %left to i65
249 %extright = zext i64 %right to i65
250 %sum = add i65 %extleft, %extright
251 %res.0 = trunc i65 %sum to i64
252 %overflow = and i65 %sum, -18446744073709551616
253 %res.1 = icmp ne i65 %overflow, 0
254 %final0 = insertvalue {i64, i1} undef, i64 %res.0, 0
255 %final1 = insertvalue {i64, i1} %final0, i1 %res.1, 1
256 ret {i64, i1} %final1
259 define i32 @test9(i32 %x, i32 %y) nounwind readnone {
261 ; X32: # %bb.0: # %entry
262 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
263 ; X32-NEXT: xorl %ecx, %ecx
264 ; X32-NEXT: cmpl $10, {{[0-9]+}}(%esp)
266 ; X32-NEXT: subl %ecx, %eax
269 ; X64-LINUX-LABEL: test9:
270 ; X64-LINUX: # %bb.0: # %entry
271 ; X64-LINUX-NEXT: movl %esi, %eax
272 ; X64-LINUX-NEXT: xorl %ecx, %ecx
273 ; X64-LINUX-NEXT: cmpl $10, %edi
274 ; X64-LINUX-NEXT: sete %cl
275 ; X64-LINUX-NEXT: subl %ecx, %eax
276 ; X64-LINUX-NEXT: retq
278 ; X64-WIN32-LABEL: test9:
279 ; X64-WIN32: # %bb.0: # %entry
280 ; X64-WIN32-NEXT: movl %edx, %eax
281 ; X64-WIN32-NEXT: xorl %edx, %edx
282 ; X64-WIN32-NEXT: cmpl $10, %ecx
283 ; X64-WIN32-NEXT: sete %dl
284 ; X64-WIN32-NEXT: subl %edx, %eax
285 ; X64-WIN32-NEXT: retq
287 %cmp = icmp eq i32 %x, 10
288 %sub = sext i1 %cmp to i32
289 %cond = add i32 %sub, %y
293 define i1 @test10(i32 %x) nounwind {
295 ; X32: # %bb.0: # %entry
296 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
297 ; X32-NEXT: incl %eax
301 ; X64-LINUX-LABEL: test10:
302 ; X64-LINUX: # %bb.0: # %entry
303 ; X64-LINUX-NEXT: incl %edi
304 ; X64-LINUX-NEXT: seto %al
305 ; X64-LINUX-NEXT: retq
307 ; X64-WIN32-LABEL: test10:
308 ; X64-WIN32: # %bb.0: # %entry
309 ; X64-WIN32-NEXT: incl %ecx
310 ; X64-WIN32-NEXT: seto %al
311 ; X64-WIN32-NEXT: retq
313 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %x, i32 1)
314 %obit = extractvalue {i32, i1} %t, 1
318 define void @test11(i32* inreg %a) nounwind {
320 ; X32: # %bb.0: # %entry
321 ; X32-NEXT: subl $-128, (%eax)
324 ; X64-LINUX-LABEL: test11:
325 ; X64-LINUX: # %bb.0: # %entry
326 ; X64-LINUX-NEXT: subl $-128, (%rdi)
327 ; X64-LINUX-NEXT: retq
329 ; X64-WIN32-LABEL: test11:
330 ; X64-WIN32: # %bb.0: # %entry
331 ; X64-WIN32-NEXT: subl $-128, (%rcx)
332 ; X64-WIN32-NEXT: retq
334 %aa = load i32, i32* %a
335 %b = add i32 %aa, 128
336 store i32 %b, i32* %a
340 define void @test12(i64* inreg %a) nounwind {
342 ; X32: # %bb.0: # %entry
343 ; X32-NEXT: addl $-2147483648, (%eax) # imm = 0x80000000
344 ; X32-NEXT: adcl $0, 4(%eax)
347 ; X64-LINUX-LABEL: test12:
348 ; X64-LINUX: # %bb.0: # %entry
349 ; X64-LINUX-NEXT: subq $-2147483648, (%rdi) # imm = 0x80000000
350 ; X64-LINUX-NEXT: retq
352 ; X64-WIN32-LABEL: test12:
353 ; X64-WIN32: # %bb.0: # %entry
354 ; X64-WIN32-NEXT: subq $-2147483648, (%rcx) # imm = 0x80000000
355 ; X64-WIN32-NEXT: retq
357 %aa = load i64, i64* %a
358 %b = add i64 %aa, 2147483648
359 store i64 %b, i64* %a
363 define void @test13(i64* inreg %a) nounwind {
365 ; X32: # %bb.0: # %entry
366 ; X32-NEXT: addl $128, (%eax)
367 ; X32-NEXT: adcl $0, 4(%eax)
370 ; X64-LINUX-LABEL: test13:
371 ; X64-LINUX: # %bb.0: # %entry
372 ; X64-LINUX-NEXT: subq $-128, (%rdi)
373 ; X64-LINUX-NEXT: retq
375 ; X64-WIN32-LABEL: test13:
376 ; X64-WIN32: # %bb.0: # %entry
377 ; X64-WIN32-NEXT: subq $-128, (%rcx)
378 ; X64-WIN32-NEXT: retq
380 %aa = load i64, i64* %a
381 %b = add i64 %aa, 128
382 store i64 %b, i64* %a
386 define i32 @inc_not(i32 %a) {
387 ; X32-LABEL: inc_not:
389 ; X32-NEXT: xorl %eax, %eax
390 ; X32-NEXT: subl {{[0-9]+}}(%esp), %eax
393 ; X64-LINUX-LABEL: inc_not:
394 ; X64-LINUX: # %bb.0:
395 ; X64-LINUX-NEXT: movl %edi, %eax
396 ; X64-LINUX-NEXT: negl %eax
397 ; X64-LINUX-NEXT: retq
399 ; X64-WIN32-LABEL: inc_not:
400 ; X64-WIN32: # %bb.0:
401 ; X64-WIN32-NEXT: movl %ecx, %eax
402 ; X64-WIN32-NEXT: negl %eax
403 ; X64-WIN32-NEXT: retq
404 %nota = xor i32 %a, -1
405 %r = add i32 %nota, 1
409 define <4 x i32> @inc_not_vec(<4 x i32> %a) nounwind {
410 ; X32-LABEL: inc_not_vec:
412 ; X32-NEXT: pushl %edi
413 ; X32-NEXT: pushl %esi
414 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
415 ; X32-NEXT: xorl %ecx, %ecx
416 ; X32-NEXT: xorl %edx, %edx
417 ; X32-NEXT: subl {{[0-9]+}}(%esp), %edx
418 ; X32-NEXT: xorl %esi, %esi
419 ; X32-NEXT: subl {{[0-9]+}}(%esp), %esi
420 ; X32-NEXT: xorl %edi, %edi
421 ; X32-NEXT: subl {{[0-9]+}}(%esp), %edi
422 ; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
423 ; X32-NEXT: movl %ecx, 12(%eax)
424 ; X32-NEXT: movl %edi, 8(%eax)
425 ; X32-NEXT: movl %esi, 4(%eax)
426 ; X32-NEXT: movl %edx, (%eax)
427 ; X32-NEXT: popl %esi
428 ; X32-NEXT: popl %edi
431 ; X64-LINUX-LABEL: inc_not_vec:
432 ; X64-LINUX: # %bb.0:
433 ; X64-LINUX-NEXT: pxor %xmm1, %xmm1
434 ; X64-LINUX-NEXT: psubd %xmm0, %xmm1
435 ; X64-LINUX-NEXT: movdqa %xmm1, %xmm0
436 ; X64-LINUX-NEXT: retq
438 ; X64-WIN32-LABEL: inc_not_vec:
439 ; X64-WIN32: # %bb.0:
440 ; X64-WIN32-NEXT: pxor %xmm0, %xmm0
441 ; X64-WIN32-NEXT: psubd (%rcx), %xmm0
442 ; X64-WIN32-NEXT: retq
443 %nota = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
444 %r = add <4 x i32> %nota, <i32 1, i32 1, i32 1, i32 1>
448 define void @uaddo1_not(i32 %a, i32* %p0, i1* %p1) {
449 ; X32-LABEL: uaddo1_not:
451 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
452 ; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
453 ; X32-NEXT: xorl %edx, %edx
454 ; X32-NEXT: subl {{[0-9]+}}(%esp), %edx
455 ; X32-NEXT: movl %edx, (%ecx)
456 ; X32-NEXT: setae (%eax)
459 ; X64-LINUX-LABEL: uaddo1_not:
460 ; X64-LINUX: # %bb.0:
461 ; X64-LINUX-NEXT: negl %edi
462 ; X64-LINUX-NEXT: movl %edi, (%rsi)
463 ; X64-LINUX-NEXT: setae (%rdx)
464 ; X64-LINUX-NEXT: retq
466 ; X64-WIN32-LABEL: uaddo1_not:
467 ; X64-WIN32: # %bb.0:
468 ; X64-WIN32-NEXT: negl %ecx
469 ; X64-WIN32-NEXT: movl %ecx, (%rdx)
470 ; X64-WIN32-NEXT: setae (%r8)
471 ; X64-WIN32-NEXT: retq
472 %nota = xor i32 %a, -1
473 %uaddo = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %nota, i32 1)
474 %r0 = extractvalue {i32, i1} %uaddo, 0
475 %r1 = extractvalue {i32, i1} %uaddo, 1
476 store i32 %r0, i32* %p0
477 store i1 %r1, i1* %p1