1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
6 ; #include <x86intrin.h>
7 ; using u64 = unsigned long long;
10 ; void test(u64& alo, u64& ahi)
14 ; bool cf = (alo += blo) < blo;
15 ; _addcarry_u64(cf, ahi, bhi, &ahi);
18 ; template void test<0ull>(u64&, u64&);
19 ; template void test<1ull>(u64&, u64&);
20 ; template void test<2ull>(u64&, u64&);
21 ; template void test<3ull>(u64&, u64&);
22 ; template void test<4ull>(u64&, u64&);
23 ; template void test<0x7fffffffffffffffull>(u64&, u64&);
24 ; template void test<0x8000000000000000ull>(u64&, u64&);
25 ; template void test<0x8000000000000001ull>(u64&, u64&);
26 ; template void test<0xffffffff80000000ull>(u64&, u64&);
27 ; template void test<0xfffffffffffffffdull>(u64&, u64&);
28 ; template void test<0xfffffffffffffffeull>(u64&, u64&);
29 ; template void test<0xffffffffffffffffull>(u64&, u64&);
31 define void @test_0(i64*, i64*) {
32 ; CHECK-LABEL: test_0:
35 %3 = load i64, i64* %1, align 8
36 %4 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 0, i64 %3, i64 0)
37 %5 = extractvalue { i8, i64 } %4, 1
38 store i64 %5, i64* %1, align 8
42 define void @test_1(i64*, i64*) {
43 ; CHECK-LABEL: test_1:
45 ; CHECK-NEXT: addq $1, (%rdi)
46 ; CHECK-NEXT: adcq $0, (%rsi)
48 %3 = load i64, i64* %0, align 8
50 store i64 %4, i64* %0, align 8
51 %5 = icmp eq i64 %4, 0
53 %7 = load i64, i64* %1, align 8
54 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
55 %9 = extractvalue { i8, i64 } %8, 1
56 store i64 %9, i64* %1, align 8
60 define void @test_2(i64*, i64*) {
61 ; CHECK-LABEL: test_2:
63 ; CHECK-NEXT: addq $2, (%rdi)
64 ; CHECK-NEXT: adcq $0, (%rsi)
66 %3 = load i64, i64* %0, align 8
68 store i64 %4, i64* %0, align 8
69 %5 = icmp ult i64 %4, 2
71 %7 = load i64, i64* %1, align 8
72 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
73 %9 = extractvalue { i8, i64 } %8, 1
74 store i64 %9, i64* %1, align 8
78 define void @test_3(i64*, i64*) {
79 ; CHECK-LABEL: test_3:
81 ; CHECK-NEXT: addq $3, (%rdi)
82 ; CHECK-NEXT: adcq $0, (%rsi)
84 %3 = load i64, i64* %0, align 8
86 store i64 %4, i64* %0, align 8
87 %5 = icmp ult i64 %4, 3
89 %7 = load i64, i64* %1, align 8
90 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
91 %9 = extractvalue { i8, i64 } %8, 1
92 store i64 %9, i64* %1, align 8
96 define void @test_4(i64*, i64*) {
97 ; CHECK-LABEL: test_4:
99 ; CHECK-NEXT: addq $4, (%rdi)
100 ; CHECK-NEXT: adcq $0, (%rsi)
102 %3 = load i64, i64* %0, align 8
104 store i64 %4, i64* %0, align 8
105 %5 = icmp ult i64 %4, 4
106 %6 = zext i1 %5 to i8
107 %7 = load i64, i64* %1, align 8
108 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
109 %9 = extractvalue { i8, i64 } %8, 1
110 store i64 %9, i64* %1, align 8
114 define void @test_9223372036854775807(i64*, i64*) {
115 ; CHECK-LABEL: test_9223372036854775807:
117 ; CHECK-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF
118 ; CHECK-NEXT: addq %rax, (%rdi)
119 ; CHECK-NEXT: adcq $0, (%rsi)
121 %3 = load i64, i64* %0, align 8
122 %4 = add i64 %3, 9223372036854775807
123 store i64 %4, i64* %0, align 8
124 %5 = icmp ult i64 %4, 9223372036854775807
125 %6 = zext i1 %5 to i8
126 %7 = load i64, i64* %1, align 8
127 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
128 %9 = extractvalue { i8, i64 } %8, 1
129 store i64 %9, i64* %1, align 8
133 define void @test_9223372036854775808(i64*, i64*) {
134 ; CHECK-LABEL: test_9223372036854775808:
136 ; CHECK-NEXT: movq (%rdi), %rax
137 ; CHECK-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
138 ; CHECK-NEXT: xorq %rax, %rcx
139 ; CHECK-NEXT: movq %rcx, (%rdi)
140 ; CHECK-NEXT: shrq $63, %rax
141 ; CHECK-NEXT: addb $-1, %al
142 ; CHECK-NEXT: adcq $0, (%rsi)
144 %3 = load i64, i64* %0, align 8
145 %4 = xor i64 %3, -9223372036854775808
146 store i64 %4, i64* %0, align 8
148 %6 = trunc i64 %5 to i8
149 %7 = load i64, i64* %1, align 8
150 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
151 %9 = extractvalue { i8, i64 } %8, 1
152 store i64 %9, i64* %1, align 8
156 define void @test_9223372036854775809(i64*, i64*) {
157 ; CHECK-LABEL: test_9223372036854775809:
159 ; CHECK-NEXT: movabsq $-9223372036854775807, %rax # imm = 0x8000000000000001
160 ; CHECK-NEXT: addq %rax, (%rdi)
161 ; CHECK-NEXT: adcq $0, (%rsi)
163 %3 = load i64, i64* %0, align 8
164 %4 = add i64 %3, -9223372036854775807
165 store i64 %4, i64* %0, align 8
166 %5 = icmp ult i64 %4, -9223372036854775807
167 %6 = zext i1 %5 to i8
168 %7 = load i64, i64* %1, align 8
169 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
170 %9 = extractvalue { i8, i64 } %8, 1
171 store i64 %9, i64* %1, align 8
175 define void @test_18446744071562067968(i64*, i64*) {
176 ; CHECK-LABEL: test_18446744071562067968:
178 ; CHECK-NEXT: addq $-2147483648, (%rdi) # imm = 0x80000000
179 ; CHECK-NEXT: adcq $0, (%rsi)
181 %3 = load i64, i64* %0, align 8
182 %4 = add i64 %3, -2147483648
183 store i64 %4, i64* %0, align 8
184 %5 = icmp ult i64 %4, -2147483648
185 %6 = zext i1 %5 to i8
186 %7 = load i64, i64* %1, align 8
187 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
188 %9 = extractvalue { i8, i64 } %8, 1
189 store i64 %9, i64* %1, align 8
193 define void @test_18446744073709551613(i64*, i64*) {
194 ; CHECK-LABEL: test_18446744073709551613:
196 ; CHECK-NEXT: addq $-3, (%rdi)
197 ; CHECK-NEXT: adcq $0, (%rsi)
199 %3 = load i64, i64* %0, align 8
201 store i64 %4, i64* %0, align 8
202 %5 = icmp ult i64 %4, -3
203 %6 = zext i1 %5 to i8
204 %7 = load i64, i64* %1, align 8
205 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
206 %9 = extractvalue { i8, i64 } %8, 1
207 store i64 %9, i64* %1, align 8
211 define void @test_18446744073709551614(i64*, i64*) {
212 ; CHECK-LABEL: test_18446744073709551614:
214 ; CHECK-NEXT: addq $-2, (%rdi)
215 ; CHECK-NEXT: adcq $0, (%rsi)
217 %3 = load i64, i64* %0, align 8
219 store i64 %4, i64* %0, align 8
220 %5 = icmp ult i64 %4, -2
221 %6 = zext i1 %5 to i8
222 %7 = load i64, i64* %1, align 8
223 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
224 %9 = extractvalue { i8, i64 } %8, 1
225 store i64 %9, i64* %1, align 8
229 define void @test_18446744073709551615(i64*, i64*) {
230 ; CHECK-LABEL: test_18446744073709551615:
232 ; CHECK-NEXT: addq $-1, (%rdi)
233 ; CHECK-NEXT: adcq $0, (%rsi)
235 %3 = load i64, i64* %0, align 8
237 store i64 %4, i64* %0, align 8
238 %5 = icmp ne i64 %3, 0
239 %6 = zext i1 %5 to i8
240 %7 = load i64, i64* %1, align 8
241 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)
242 %9 = extractvalue { i8, i64 } %8, 1
243 store i64 %9, i64* %1, align 8
247 define i1 @illegal_type(i17 %x, i17* %p) {
248 ; CHECK-LABEL: illegal_type:
250 ; CHECK-NEXT: addl $29, %edi
251 ; CHECK-NEXT: movw %di, (%rsi)
252 ; CHECK-NEXT: andl $131071, %edi # imm = 0x1FFFF
253 ; CHECK-NEXT: movl %edi, %eax
254 ; CHECK-NEXT: shrl $16, %eax
255 ; CHECK-NEXT: movb %al, 2(%rsi)
256 ; CHECK-NEXT: cmpl $29, %edi
257 ; CHECK-NEXT: setb %al
260 store i17 %a, i17* %p
261 %ov = icmp ult i17 %a, 29
265 ; The overflow check may be against the input rather than the sum.
267 define i1 @uaddo_i64_increment_alt(i64 %x, i64* %p) {
268 ; CHECK-LABEL: uaddo_i64_increment_alt:
270 ; CHECK-NEXT: incq %rdi
271 ; CHECK-NEXT: sete %al
272 ; CHECK-NEXT: movq %rdi, (%rsi)
275 store i64 %a, i64* %p
276 %ov = icmp eq i64 %x, -1
280 ; Make sure insertion is done correctly based on dominance.
282 define i1 @uaddo_i64_increment_alt_dom(i64 %x, i64* %p) {
283 ; CHECK-LABEL: uaddo_i64_increment_alt_dom:
285 ; CHECK-NEXT: incq %rdi
286 ; CHECK-NEXT: sete %al
287 ; CHECK-NEXT: movq %rdi, (%rsi)
289 %ov = icmp eq i64 %x, -1
291 store i64 %a, i64* %p
295 ; The overflow check may be against the input rather than the sum.
297 define i1 @uaddo_i64_decrement_alt(i64 %x, i64* %p) {
298 ; CHECK-LABEL: uaddo_i64_decrement_alt:
300 ; CHECK-NEXT: addq $-1, %rdi
301 ; CHECK-NEXT: setb %al
302 ; CHECK-NEXT: movq %rdi, (%rsi)
305 store i64 %a, i64* %p
306 %ov = icmp ne i64 %x, 0
310 ; Make sure insertion is done correctly based on dominance.
312 define i1 @uaddo_i64_decrement_alt_dom(i64 %x, i64* %p) {
313 ; CHECK-LABEL: uaddo_i64_decrement_alt_dom:
315 ; CHECK-NEXT: addq $-1, %rdi
316 ; CHECK-NEXT: setb %al
317 ; CHECK-NEXT: movq %rdi, (%rsi)
319 %ov = icmp ne i64 %x, 0
321 store i64 %a, i64* %p
325 declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)