[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / X86 / addcarry.ll
blob0db0d4ebd43c215f5b2d996954546a40f5d4a507
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
4 declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)
5 declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #1
7 define i128 @add128(i128 %a, i128 %b) nounwind {
8 ; CHECK-LABEL: add128:
9 ; CHECK:       # %bb.0: # %entry
10 ; CHECK-NEXT:    movq %rdi, %rax
11 ; CHECK-NEXT:    addq %rdx, %rax
12 ; CHECK-NEXT:    adcq %rcx, %rsi
13 ; CHECK-NEXT:    movq %rsi, %rdx
14 ; CHECK-NEXT:    retq
15 entry:
16   %0 = add i128 %a, %b
17   ret i128 %0
20 define void @add128_rmw(i128* %a, i128 %b) nounwind {
21 ; CHECK-LABEL: add128_rmw:
22 ; CHECK:       # %bb.0: # %entry
23 ; CHECK-NEXT:    addq %rsi, (%rdi)
24 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
25 ; CHECK-NEXT:    retq
26 entry:
27   %0 = load i128, i128* %a
28   %1 = add i128 %0, %b
29   store i128 %1, i128* %a
30   ret void
33 define void @add128_rmw2(i128 %a, i128* %b) nounwind {
34 ; CHECK-LABEL: add128_rmw2:
35 ; CHECK:       # %bb.0: # %entry
36 ; CHECK-NEXT:    addq %rdi, (%rdx)
37 ; CHECK-NEXT:    adcq %rsi, 8(%rdx)
38 ; CHECK-NEXT:    retq
39 entry:
40   %0 = load i128, i128* %b
41   %1 = add i128 %a, %0
42   store i128 %1, i128* %b
43   ret void
46 define i256 @add256(i256 %a, i256 %b) nounwind {
47 ; CHECK-LABEL: add256:
48 ; CHECK:       # %bb.0: # %entry
49 ; CHECK-NEXT:    movq %rdi, %rax
50 ; CHECK-NEXT:    addq %r9, %rsi
51 ; CHECK-NEXT:    adcq {{[0-9]+}}(%rsp), %rdx
52 ; CHECK-NEXT:    adcq {{[0-9]+}}(%rsp), %rcx
53 ; CHECK-NEXT:    adcq {{[0-9]+}}(%rsp), %r8
54 ; CHECK-NEXT:    movq %rdx, 8(%rdi)
55 ; CHECK-NEXT:    movq %rsi, (%rdi)
56 ; CHECK-NEXT:    movq %rcx, 16(%rdi)
57 ; CHECK-NEXT:    movq %r8, 24(%rdi)
58 ; CHECK-NEXT:    retq
59 entry:
60   %0 = add i256 %a, %b
61   ret i256 %0
64 define void @add256_rmw(i256* %a, i256 %b) nounwind {
65 ; CHECK-LABEL: add256_rmw:
66 ; CHECK:       # %bb.0: # %entry
67 ; CHECK-NEXT:    addq %rsi, (%rdi)
68 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
69 ; CHECK-NEXT:    adcq %rcx, 16(%rdi)
70 ; CHECK-NEXT:    adcq %r8, 24(%rdi)
71 ; CHECK-NEXT:    retq
72 entry:
73   %0 = load i256, i256* %a
74   %1 = add i256 %0, %b
75   store i256 %1, i256* %a
76   ret void
79 define void @add256_rmw2(i256 %a, i256* %b) nounwind {
80 ; CHECK-LABEL: add256_rmw2:
81 ; CHECK:       # %bb.0: # %entry
82 ; CHECK-NEXT:    addq %rdi, (%r8)
83 ; CHECK-NEXT:    adcq %rsi, 8(%r8)
84 ; CHECK-NEXT:    adcq %rdx, 16(%r8)
85 ; CHECK-NEXT:    adcq %rcx, 24(%r8)
86 ; CHECK-NEXT:    retq
87 entry:
88   %0 = load i256, i256* %b
89   %1 = add i256 %a, %0
90   store i256 %1, i256* %b
91   ret void
94 define void @a(i64* nocapture %s, i64* nocapture %t, i64 %a, i64 %b, i64 %c) nounwind {
95 ; CHECK-LABEL: a:
96 ; CHECK:       # %bb.0: # %entry
97 ; CHECK-NEXT:    addq %rcx, %rdx
98 ; CHECK-NEXT:    adcq $0, %r8
99 ; CHECK-NEXT:    movq %r8, (%rdi)
100 ; CHECK-NEXT:    movq %rdx, (%rsi)
101 ; CHECK-NEXT:    retq
102 entry:
103  %0 = zext i64 %a to i128
104  %1 = zext i64 %b to i128
105  %2 = add i128 %1, %0
106  %3 = zext i64 %c to i128
107  %4 = shl i128 %3, 64
108  %5 = add i128 %4, %2
109  %6 = lshr i128 %5, 64
110  %7 = trunc i128 %6 to i64
111  store i64 %7, i64* %s, align 8
112  %8 = trunc i128 %2 to i64
113  store i64 %8, i64* %t, align 8
114  ret void
117 define void @b(i32* nocapture %r, i64 %a, i64 %b, i32 %c) nounwind {
118 ; CHECK-LABEL: b:
119 ; CHECK:       # %bb.0: # %entry
120 ; CHECK-NEXT:    addq %rdx, %rsi
121 ; CHECK-NEXT:    adcl $0, %ecx
122 ; CHECK-NEXT:    movl %ecx, (%rdi)
123 ; CHECK-NEXT:    retq
124 entry:
125  %0 = zext i64 %a to i128
126  %1 = zext i64 %b to i128
127  %2 = zext i32 %c to i128
128  %3 = add i128 %1, %0
129  %4 = lshr i128 %3, 64
130  %5 = add i128 %4, %2
131  %6 = trunc i128 %5 to i32
132  store i32 %6, i32* %r, align 4
133  ret void
136 define void @c(i16* nocapture %r, i64 %a, i64 %b, i16 %c) nounwind {
137 ; CHECK-LABEL: c:
138 ; CHECK:       # %bb.0: # %entry
139 ; CHECK-NEXT:    addq %rdx, %rsi
140 ; CHECK-NEXT:    adcw $0, %cx
141 ; CHECK-NEXT:    movw %cx, (%rdi)
142 ; CHECK-NEXT:    retq
143 entry:
144  %0 = zext i64 %a to i128
145  %1 = zext i64 %b to i128
146  %2 = zext i16 %c to i128
147  %3 = add i128 %1, %0
148  %4 = lshr i128 %3, 64
149  %5 = add i128 %4, %2
150  %6 = trunc i128 %5 to i16
151  store i16 %6, i16* %r, align 4
152  ret void
155 define void @d(i8* nocapture %r, i64 %a, i64 %b, i8 %c) nounwind {
156 ; CHECK-LABEL: d:
157 ; CHECK:       # %bb.0: # %entry
158 ; CHECK-NEXT:    addq %rdx, %rsi
159 ; CHECK-NEXT:    adcb $0, %cl
160 ; CHECK-NEXT:    movb %cl, (%rdi)
161 ; CHECK-NEXT:    retq
162 entry:
163  %0 = zext i64 %a to i128
164  %1 = zext i64 %b to i128
165  %2 = zext i8 %c to i128
166  %3 = add i128 %1, %0
167  %4 = lshr i128 %3, 64
168  %5 = add i128 %4, %2
169  %6 = trunc i128 %5 to i8
170  store i8 %6, i8* %r, align 4
171  ret void
174 define i8 @e(i32* nocapture %a, i32 %b) nounwind {
175 ; CHECK-LABEL: e:
176 ; CHECK:       # %bb.0:
177 ; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
178 ; CHECK-NEXT:    movl (%rdi), %ecx
179 ; CHECK-NEXT:    leal (%rsi,%rcx), %edx
180 ; CHECK-NEXT:    addl %esi, %edx
181 ; CHECK-NEXT:    setb %al
182 ; CHECK-NEXT:    addl %esi, %ecx
183 ; CHECK-NEXT:    movl %edx, (%rdi)
184 ; CHECK-NEXT:    adcb $0, %al
185 ; CHECK-NEXT:    retq
186   %1 = load i32, i32* %a, align 4
187   %2 = add i32 %1, %b
188   %3 = icmp ult i32 %2, %b
189   %4 = zext i1 %3 to i8
190   %5 = add i32 %2, %b
191   store i32 %5, i32* %a, align 4
192   %6 = icmp ult i32 %5, %b
193   %7 = zext i1 %6 to i8
194   %8 = add nuw nsw i8 %7, %4
195   ret i8 %8
198 %scalar = type { [4 x i64] }
200 define %scalar @pr31719(%scalar* nocapture readonly %this, %scalar %arg.b) {
201 ; CHECK-LABEL: pr31719:
202 ; CHECK:       # %bb.0: # %entry
203 ; CHECK-NEXT:    movq %rdi, %rax
204 ; CHECK-NEXT:    addq (%rsi), %rdx
205 ; CHECK-NEXT:    adcq 8(%rsi), %rcx
206 ; CHECK-NEXT:    adcq 16(%rsi), %r8
207 ; CHECK-NEXT:    adcq 24(%rsi), %r9
208 ; CHECK-NEXT:    movq %rdx, (%rdi)
209 ; CHECK-NEXT:    movq %rcx, 8(%rdi)
210 ; CHECK-NEXT:    movq %r8, 16(%rdi)
211 ; CHECK-NEXT:    movq %r9, 24(%rdi)
212 ; CHECK-NEXT:    retq
213 entry:
214   %0 = extractvalue %scalar %arg.b, 0
215   %.elt = extractvalue [4 x i64] %0, 0
216   %.elt24 = extractvalue [4 x i64] %0, 1
217   %.elt26 = extractvalue [4 x i64] %0, 2
218   %.elt28 = extractvalue [4 x i64] %0, 3
219   %1 = getelementptr inbounds %scalar , %scalar* %this, i64 0, i32 0, i64 0
220   %2 = load i64, i64* %1, align 8
221   %3 = zext i64 %2 to i128
222   %4 = zext i64 %.elt to i128
223   %5 = add nuw nsw i128 %3, %4
224   %6 = trunc i128 %5 to i64
225   %7 = lshr i128 %5, 64
226   %8 = getelementptr inbounds %scalar , %scalar * %this, i64 0, i32 0, i64 1
227   %9 = load i64, i64* %8, align 8
228   %10 = zext i64 %9 to i128
229   %11 = zext i64 %.elt24 to i128
230   %12 = add nuw nsw i128 %10, %11
231   %13 = add nuw nsw i128 %12, %7
232   %14 = trunc i128 %13 to i64
233   %15 = lshr i128 %13, 64
234   %16 = getelementptr inbounds %scalar , %scalar* %this, i64 0, i32 0, i64 2
235   %17 = load i64, i64* %16, align 8
236   %18 = zext i64 %17 to i128
237   %19 = zext i64 %.elt26 to i128
238   %20 = add nuw nsw i128 %18, %19
239   %21 = add nuw nsw i128 %20, %15
240   %22 = trunc i128 %21 to i64
241   %23 = lshr i128 %21, 64
242   %24 = getelementptr inbounds %scalar , %scalar* %this, i64 0, i32 0, i64 3
243   %25 = load i64, i64* %24, align 8
244   %26 = zext i64 %25 to i128
245   %27 = zext i64 %.elt28 to i128
246   %28 = add nuw nsw i128 %26, %27
247   %29 = add nuw nsw i128 %28, %23
248   %30 = trunc i128 %29 to i64
249   %31 = insertvalue [4 x i64] undef, i64 %6, 0
250   %32 = insertvalue [4 x i64] %31, i64 %14, 1
251   %33 = insertvalue [4 x i64] %32, i64 %22, 2
252   %34 = insertvalue [4 x i64] %33, i64 %30, 3
253   %35 = insertvalue %scalar undef, [4 x i64] %34, 0
254   ret %scalar %35
257 %accumulator= type { i64, i64, i32 }
259 define void @muladd(%accumulator* nocapture %this, i64 %arg.a, i64 %arg.b) {
260 ; CHECK-LABEL: muladd:
261 ; CHECK:       # %bb.0: # %entry
262 ; CHECK-NEXT:    movq %rdx, %rax
263 ; CHECK-NEXT:    mulq %rsi
264 ; CHECK-NEXT:    addq %rax, (%rdi)
265 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
266 ; CHECK-NEXT:    adcl $0, 16(%rdi)
267 ; CHECK-NEXT:    retq
268 entry:
269   %0 = zext i64 %arg.a to i128
270   %1 = zext i64 %arg.b to i128
271   %2 = mul nuw i128 %1, %0
272   %3 = getelementptr inbounds %accumulator, %accumulator* %this, i64 0, i32 0
273   %4 = load i64, i64* %3, align 8
274   %5 = zext i64 %4 to i128
275   %6 = add i128 %5, %2
276   %7 = trunc i128 %6 to i64
277   store i64 %7, i64* %3, align 8
278   %8 = lshr i128 %6, 64
279   %9 = getelementptr inbounds %accumulator, %accumulator* %this, i64 0, i32 1
280   %10 = load i64, i64* %9, align 8
281   %11 = zext i64 %10 to i128
282   %12 = add nuw nsw i128 %8, %11
283   %13 = trunc i128 %12 to i64
284   store i64 %13, i64* %9, align 8
285   %14 = lshr i128 %12, 64
286   %15 = getelementptr inbounds %accumulator, %accumulator* %this, i64 0, i32 2
287   %16 = load i32, i32* %15, align 4
288   %17 = zext i32 %16 to i128
289   %18 = add nuw nsw i128 %14, %17
290   %19 = trunc i128 %18 to i32
291   store i32 %19, i32* %15, align 4
292   ret void
295 define i64 @shiftadd(i64 %a, i64 %b, i64 %c, i64 %d) {
296 ; CHECK-LABEL: shiftadd:
297 ; CHECK:       # %bb.0: # %entry
298 ; CHECK-NEXT:    movq %rdx, %rax
299 ; CHECK-NEXT:    addq %rsi, %rdi
300 ; CHECK-NEXT:    adcq %rcx, %rax
301 ; CHECK-NEXT:    retq
302 entry:
303   %0 = zext i64 %a to i128
304   %1 = zext i64 %b to i128
305   %2 = add i128 %0, %1
306   %3 = lshr i128 %2, 64
307   %4 = trunc i128 %3 to i64
308   %5 = add i64 %c, %d
309   %6 = add i64 %4, %5
310   ret i64 %6
313 %S = type { [4 x i64] }
315 define %S @readd(%S* nocapture readonly %this, %S %arg.b) {
316 ; CHECK-LABEL: readd:
317 ; CHECK:       # %bb.0: # %entry
318 ; CHECK-NEXT:    movq %rdi, %rax
319 ; CHECK-NEXT:    addq (%rsi), %rdx
320 ; CHECK-NEXT:    movq 8(%rsi), %r11
321 ; CHECK-NEXT:    adcq $0, %r11
322 ; CHECK-NEXT:    setb %r10b
323 ; CHECK-NEXT:    movzbl %r10b, %edi
324 ; CHECK-NEXT:    addq %rcx, %r11
325 ; CHECK-NEXT:    adcq 16(%rsi), %rdi
326 ; CHECK-NEXT:    setb %cl
327 ; CHECK-NEXT:    movzbl %cl, %ecx
328 ; CHECK-NEXT:    addq %r8, %rdi
329 ; CHECK-NEXT:    adcq 24(%rsi), %rcx
330 ; CHECK-NEXT:    addq %r9, %rcx
331 ; CHECK-NEXT:    movq %rdx, (%rax)
332 ; CHECK-NEXT:    movq %r11, 8(%rax)
333 ; CHECK-NEXT:    movq %rdi, 16(%rax)
334 ; CHECK-NEXT:    movq %rcx, 24(%rax)
335 ; CHECK-NEXT:    retq
336 entry:
337   %0 = extractvalue %S %arg.b, 0
338   %.elt6 = extractvalue [4 x i64] %0, 1
339   %.elt8 = extractvalue [4 x i64] %0, 2
340   %.elt10 = extractvalue [4 x i64] %0, 3
341   %.elt = extractvalue [4 x i64] %0, 0
342   %1 = getelementptr inbounds %S, %S* %this, i64 0, i32 0, i64 0
343   %2 = load i64, i64* %1, align 8
344   %3 = zext i64 %2 to i128
345   %4 = zext i64 %.elt to i128
346   %5 = add nuw nsw i128 %3, %4
347   %6 = trunc i128 %5 to i64
348   %7 = lshr i128 %5, 64
349   %8 = getelementptr inbounds %S, %S* %this, i64 0, i32 0, i64 1
350   %9 = load i64, i64* %8, align 8
351   %10 = zext i64 %9 to i128
352   %11 = add nuw nsw i128 %7, %10
353   %12 = zext i64 %.elt6 to i128
354   %13 = add nuw nsw i128 %11, %12
355   %14 = trunc i128 %13 to i64
356   %15 = lshr i128 %13, 64
357   %16 = getelementptr inbounds %S, %S* %this, i64 0, i32 0, i64 2
358   %17 = load i64, i64* %16, align 8
359   %18 = zext i64 %17 to i128
360   %19 = add nuw nsw i128 %15, %18
361   %20 = zext i64 %.elt8 to i128
362   %21 = add nuw nsw i128 %19, %20
363   %22 = lshr i128 %21, 64
364   %23 = trunc i128 %21 to i64
365   %24 = getelementptr inbounds %S, %S* %this, i64 0,i32 0, i64 3
366   %25 = load i64, i64* %24, align 8
367   %26 = zext i64 %25 to i128
368   %27 = add nuw nsw i128 %22, %26
369   %28 = zext i64 %.elt10 to i128
370   %29 = add nuw nsw i128 %27, %28
371   %30 = trunc i128 %29 to i64
372   %31 = insertvalue [4 x i64] undef, i64 %6, 0
373   %32 = insertvalue [4 x i64] %31, i64 %14, 1
374   %33 = insertvalue [4 x i64] %32, i64 %23, 2
375   %34 = insertvalue [4 x i64] %33, i64 %30, 3
376   %35 = insertvalue %S undef, [4 x i64] %34, 0
377   ret %S %35
380 define i128 @addcarry1_not(i128 %n) {
381 ; CHECK-LABEL: addcarry1_not:
382 ; CHECK:       # %bb.0:
383 ; CHECK-NEXT:    movq %rdi, %rax
384 ; CHECK-NEXT:    xorl %edx, %edx
385 ; CHECK-NEXT:    negq %rax
386 ; CHECK-NEXT:    sbbq %rsi, %rdx
387 ; CHECK-NEXT:    retq
388   %1 = xor i128 %n, -1
389   %2 = add i128 %1, 1
390   ret i128 %2
393 define i128 @addcarry_to_subcarry(i64 %a, i64 %b) {
394 ; CHECK-LABEL: addcarry_to_subcarry:
395 ; CHECK:       # %bb.0:
396 ; CHECK-NEXT:    movq %rdi, %rax
397 ; CHECK-NEXT:    cmpq %rsi, %rdi
398 ; CHECK-NEXT:    notq %rsi
399 ; CHECK-NEXT:    setae %cl
400 ; CHECK-NEXT:    addb $-1, %cl
401 ; CHECK-NEXT:    adcq $0, %rax
402 ; CHECK-NEXT:    setb %cl
403 ; CHECK-NEXT:    movzbl %cl, %edx
404 ; CHECK-NEXT:    addq %rsi, %rax
405 ; CHECK-NEXT:    adcq $0, %rdx
406 ; CHECK-NEXT:    retq
407   %notb = xor i64 %b, -1
408   %notb128 = zext i64 %notb to i128
409   %a128 = zext i64 %a to i128
410   %sum1 = add i128 %a128, 1
411   %sub1 = add i128 %sum1, %notb128
412   %hi = lshr i128 %sub1, 64
413   %sum2 = add i128 %hi, %a128
414   %sub2 = add i128 %sum2, %notb128
415   ret i128 %sub2
418 %struct.U320 = type { [5 x i64] }
420 define i32 @add_U320_without_i128_add(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
421 ; CHECK-LABEL: add_U320_without_i128_add:
422 ; CHECK:       # %bb.0:
423 ; CHECK-NEXT:    pushq %r14
424 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
425 ; CHECK-NEXT:    pushq %rbx
426 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
427 ; CHECK-NEXT:    .cfi_offset %rbx, -24
428 ; CHECK-NEXT:    .cfi_offset %r14, -16
429 ; CHECK-NEXT:    movq 16(%rdi), %rax
430 ; CHECK-NEXT:    leaq (%rax,%rcx), %r10
431 ; CHECK-NEXT:    addq %rsi, (%rdi)
432 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
433 ; CHECK-NEXT:    movq %rax, %rdx
434 ; CHECK-NEXT:    adcq %rcx, %rdx
435 ; CHECK-NEXT:    movq 24(%rdi), %r11
436 ; CHECK-NEXT:    leaq (%r8,%r11), %r14
437 ; CHECK-NEXT:    xorl %ebx, %ebx
438 ; CHECK-NEXT:    cmpq %r10, %rdx
439 ; CHECK-NEXT:    setb %bl
440 ; CHECK-NEXT:    addq %rcx, %rax
441 ; CHECK-NEXT:    adcq %r14, %rbx
442 ; CHECK-NEXT:    movq 32(%rdi), %r10
443 ; CHECK-NEXT:    leaq (%r9,%r10), %rcx
444 ; CHECK-NEXT:    xorl %esi, %esi
445 ; CHECK-NEXT:    cmpq %r14, %rbx
446 ; CHECK-NEXT:    setb %sil
447 ; CHECK-NEXT:    addq %r11, %r8
448 ; CHECK-NEXT:    adcq %rcx, %rsi
449 ; CHECK-NEXT:    xorl %eax, %eax
450 ; CHECK-NEXT:    cmpq %rcx, %rsi
451 ; CHECK-NEXT:    setb %al
452 ; CHECK-NEXT:    addq %r10, %r9
453 ; CHECK-NEXT:    movq %rdx, 16(%rdi)
454 ; CHECK-NEXT:    movq %rbx, 24(%rdi)
455 ; CHECK-NEXT:    movq %rsi, 32(%rdi)
456 ; CHECK-NEXT:    adcl $0, %eax
457 ; CHECK-NEXT:    popq %rbx
458 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
459 ; CHECK-NEXT:    popq %r14
460 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
461 ; CHECK-NEXT:    retq
462   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
463   %8 = load i64, i64* %7, align 8
464   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
465   %10 = load i64, i64* %9, align 8
466   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
467   %12 = load i64, i64* %11, align 8
468   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
469   %14 = load i64, i64* %13, align 8
470   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
471   %16 = load i64, i64* %15, align 8
472   %17 = add i64 %8, %1
473   %18 = add i64 %10, %2
474   %19 = icmp ult i64 %17, %1
475   %20 = zext i1 %19 to i64
476   %21 = add i64 %18, %20
477   %22 = add i64 %12, %3
478   %23 = icmp ult i64 %18, %10
479   %24 = zext i1 %23 to i64
480   %25 = icmp ult i64 %21, %18
481   %26 = zext i1 %25 to i64
482   %27 = add i64 %22, %24
483   %28 = add i64 %27, %26
484   %29 = add i64 %14, %4
485   %30 = icmp ult i64 %22, %12
486   %31 = zext i1 %30 to i64
487   %32 = icmp ult i64 %28, %22
488   %33 = zext i1 %32 to i64
489   %34 = add i64 %29, %31
490   %35 = add i64 %34, %33
491   %36 = add i64 %16, %5
492   %37 = icmp ult i64 %29, %14
493   %38 = zext i1 %37 to i64
494   %39 = icmp ult i64 %35, %29
495   %40 = zext i1 %39 to i64
496   %41 = add i64 %36, %38
497   %42 = add i64 %41, %40
498   store i64 %17, i64* %7, align 8
499   store i64 %21, i64* %9, align 8
500   store i64 %28, i64* %11, align 8
501   store i64 %35, i64* %13, align 8
502   store i64 %42, i64* %15, align 8
503   %43 = icmp ult i64 %36, %16
504   %44 = zext i1 %43 to i32
505   %45 = icmp ult i64 %42, %36
506   %46 = zext i1 %45 to i32
507   %47 = add nuw nsw i32 %46, %44
508   ret i32 %47
511 define i32 @add_U320_without_i128_or(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
512 ; CHECK-LABEL: add_U320_without_i128_or:
513 ; CHECK:       # %bb.0:
514 ; CHECK-NEXT:    addq %rsi, (%rdi)
515 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
516 ; CHECK-NEXT:    adcq %rcx, 16(%rdi)
517 ; CHECK-NEXT:    adcq %r8, 24(%rdi)
518 ; CHECK-NEXT:    adcq %r9, 32(%rdi)
519 ; CHECK-NEXT:    setb %al
520 ; CHECK-NEXT:    movzbl %al, %eax
521 ; CHECK-NEXT:    retq
522   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
523   %8 = load i64, i64* %7, align 8
524   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
525   %10 = load i64, i64* %9, align 8
526   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
527   %12 = load i64, i64* %11, align 8
528   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
529   %14 = load i64, i64* %13, align 8
530   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
531   %16 = load i64, i64* %15, align 8
532   %17 = add i64 %8, %1
533   %18 = add i64 %10, %2
534   %19 = icmp ult i64 %17, %1
535   %20 = zext i1 %19 to i64
536   %21 = add i64 %18, %20
537   %22 = add i64 %12, %3
538   %23 = icmp ult i64 %18, %10
539   %24 = icmp ult i64 %21, %18
540   %25 = or i1 %23, %24
541   %26 = zext i1 %25 to i64
542   %27 = add i64 %22, %26
543   %28 = add i64 %14, %4
544   %29 = icmp ult i64 %22, %12
545   %30 = icmp ult i64 %27, %22
546   %31 = or i1 %29, %30
547   %32 = zext i1 %31 to i64
548   %33 = add i64 %28, %32
549   %34 = add i64 %16, %5
550   %35 = icmp ult i64 %28, %14
551   %36 = icmp ult i64 %33, %28
552   %37 = or i1 %35, %36
553   %38 = zext i1 %37 to i64
554   %39 = add i64 %34, %38
555   store i64 %17, i64* %7, align 8
556   store i64 %21, i64* %9, align 8
557   store i64 %27, i64* %11, align 8
558   store i64 %33, i64* %13, align 8
559   store i64 %39, i64* %15, align 8
560   %40 = icmp ult i64 %34, %16
561   %41 = icmp ult i64 %39, %34
562   %42 = or i1 %40, %41
563   %43 = zext i1 %42 to i32
564   ret i32 %43
567 define i32 @add_U320_without_i128_xor(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
568 ; CHECK-LABEL: add_U320_without_i128_xor:
569 ; CHECK:       # %bb.0:
570 ; CHECK-NEXT:    addq %rsi, (%rdi)
571 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
572 ; CHECK-NEXT:    adcq %rcx, 16(%rdi)
573 ; CHECK-NEXT:    adcq %r8, 24(%rdi)
574 ; CHECK-NEXT:    adcq %r9, 32(%rdi)
575 ; CHECK-NEXT:    setb %al
576 ; CHECK-NEXT:    movzbl %al, %eax
577 ; CHECK-NEXT:    retq
578   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
579   %8 = load i64, i64* %7, align 8
580   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
581   %10 = load i64, i64* %9, align 8
582   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
583   %12 = load i64, i64* %11, align 8
584   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
585   %14 = load i64, i64* %13, align 8
586   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
587   %16 = load i64, i64* %15, align 8
588   %17 = add i64 %8, %1
589   %18 = add i64 %10, %2
590   %19 = icmp ult i64 %17, %1
591   %20 = zext i1 %19 to i64
592   %21 = add i64 %18, %20
593   %22 = add i64 %12, %3
594   %23 = icmp ult i64 %18, %10
595   %24 = icmp ult i64 %21, %18
596   %25 = xor i1 %23, %24
597   %26 = zext i1 %25 to i64
598   %27 = add i64 %22, %26
599   %28 = add i64 %14, %4
600   %29 = icmp ult i64 %22, %12
601   %30 = icmp ult i64 %27, %22
602   %31 = xor i1 %29, %30
603   %32 = zext i1 %31 to i64
604   %33 = add i64 %28, %32
605   %34 = add i64 %16, %5
606   %35 = icmp ult i64 %28, %14
607   %36 = icmp ult i64 %33, %28
608   %37 = xor i1 %35, %36
609   %38 = zext i1 %37 to i64
610   %39 = add i64 %34, %38
611   store i64 %17, i64* %7, align 8
612   store i64 %21, i64* %9, align 8
613   store i64 %27, i64* %11, align 8
614   store i64 %33, i64* %13, align 8
615   store i64 %39, i64* %15, align 8
616   %40 = icmp ult i64 %34, %16
617   %41 = icmp ult i64 %39, %34
618   %42 = xor i1 %40, %41
619   %43 = zext i1 %42 to i32
620   ret i32 %43
623 ; Either the primary addition can overflow or the addition of the carry, but
624 ; they cannot both overflow.
625 define i32 @bogus_add_U320_without_i128_and(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
626 ; CHECK-LABEL: bogus_add_U320_without_i128_and:
627 ; CHECK:       # %bb.0:
628 ; CHECK-NEXT:    addq %rsi, (%rdi)
629 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
630 ; CHECK-NEXT:    addq %rcx, 16(%rdi)
631 ; CHECK-NEXT:    addq %r8, 24(%rdi)
632 ; CHECK-NEXT:    addq %r9, 32(%rdi)
633 ; CHECK-NEXT:    xorl %eax, %eax
634 ; CHECK-NEXT:    retq
635   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
636   %8 = load i64, i64* %7, align 8
637   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
638   %10 = load i64, i64* %9, align 8
639   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
640   %12 = load i64, i64* %11, align 8
641   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
642   %14 = load i64, i64* %13, align 8
643   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
644   %16 = load i64, i64* %15, align 8
645   %17 = add i64 %8, %1
646   %18 = add i64 %10, %2
647   %19 = icmp ult i64 %17, %1
648   %20 = zext i1 %19 to i64
649   %21 = add i64 %18, %20
650   %22 = add i64 %12, %3
651   %23 = icmp ult i64 %18, %10
652   %24 = icmp ult i64 %21, %18
653   %25 = and i1 %23, %24
654   %26 = zext i1 %25 to i64
655   %27 = add i64 %22, %26
656   %28 = add i64 %14, %4
657   %29 = icmp ult i64 %22, %12
658   %30 = icmp ult i64 %27, %22
659   %31 = and i1 %29, %30
660   %32 = zext i1 %31 to i64
661   %33 = add i64 %28, %32
662   %34 = add i64 %16, %5
663   %35 = icmp ult i64 %28, %14
664   %36 = icmp ult i64 %33, %28
665   %37 = and i1 %35, %36
666   %38 = zext i1 %37 to i64
667   %39 = add i64 %34, %38
668   store i64 %17, i64* %7, align 8
669   store i64 %21, i64* %9, align 8
670   store i64 %27, i64* %11, align 8
671   store i64 %33, i64* %13, align 8
672   store i64 %39, i64* %15, align 8
673   %40 = icmp ult i64 %34, %16
674   %41 = icmp ult i64 %39, %34
675   %42 = and i1 %40, %41
676   %43 = zext i1 %42 to i32
677   ret i32 %43
680 define void @add_U320_without_i128_or_no_ret(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
681 ; CHECK-LABEL: add_U320_without_i128_or_no_ret:
682 ; CHECK:       # %bb.0:
683 ; CHECK-NEXT:    addq %rsi, (%rdi)
684 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
685 ; CHECK-NEXT:    adcq %rcx, 16(%rdi)
686 ; CHECK-NEXT:    adcq %r8, 24(%rdi)
687 ; CHECK-NEXT:    adcq %r9, 32(%rdi)
688 ; CHECK-NEXT:    retq
689   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
690   %8 = load i64, i64* %7, align 8
691   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
692   %10 = load i64, i64* %9, align 8
693   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
694   %12 = load i64, i64* %11, align 8
695   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
696   %14 = load i64, i64* %13, align 8
697   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
698   %16 = load i64, i64* %15, align 8
699   %17 = add i64 %8, %1
700   %18 = add i64 %10, %2
701   %19 = icmp ult i64 %17, %1
702   %20 = zext i1 %19 to i64
703   %21 = add i64 %18, %20
704   %22 = add i64 %12, %3
705   %23 = icmp ult i64 %18, %10
706   %24 = icmp ult i64 %21, %18
707   %25 = or i1 %23, %24
708   %26 = zext i1 %25 to i64
709   %27 = add i64 %22, %26
710   %28 = add i64 %14, %4
711   %29 = icmp ult i64 %22, %12
712   %30 = icmp ult i64 %27, %22
713   %31 = or i1 %29, %30
714   %32 = zext i1 %31 to i64
715   %33 = add i64 %28, %32
716   %34 = add i64 %16, %5
717   %35 = icmp ult i64 %28, %14
718   %36 = icmp ult i64 %33, %28
719   %37 = or i1 %35, %36
720   %38 = zext i1 %37 to i64
721   %39 = add i64 %34, %38
722   store i64 %17, i64* %7, align 8
723   store i64 %21, i64* %9, align 8
724   store i64 %27, i64* %11, align 8
725   store i64 %33, i64* %13, align 8
726   store i64 %39, i64* %15, align 8
727   ret void
730 define i32 @add_U320_uaddo(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
731 ; CHECK-LABEL: add_U320_uaddo:
732 ; CHECK:       # %bb.0:
733 ; CHECK-NEXT:    addq %rsi, (%rdi)
734 ; CHECK-NEXT:    adcq %rdx, 8(%rdi)
735 ; CHECK-NEXT:    adcq %rcx, 16(%rdi)
736 ; CHECK-NEXT:    adcq %r8, 24(%rdi)
737 ; CHECK-NEXT:    adcq %r9, 32(%rdi)
738 ; CHECK-NEXT:    setb %al
739 ; CHECK-NEXT:    movzbl %al, %eax
740 ; CHECK-NEXT:    retq
741   %7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
742   %8 = load i64, i64* %7, align 8
743   %9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
744   %10 = load i64, i64* %9, align 8
745   %11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
746   %12 = load i64, i64* %11, align 8
747   %13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
748   %14 = load i64, i64* %13, align 8
749   %15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
750   %16 = load i64, i64* %15, align 8
751   %17 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %8, i64 %1)
752   %18 = extractvalue { i64, i1 } %17, 1
753   %19 = extractvalue { i64, i1 } %17, 0
754   %20 = zext i1 %18 to i64
755   %21 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %10, i64 %2)
756   %22 = extractvalue { i64, i1 } %21, 1
757   %23 = extractvalue { i64, i1 } %21, 0
758   %24 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %23, i64 %20)
759   %25 = extractvalue { i64, i1 } %24, 1
760   %26 = extractvalue { i64, i1 } %24, 0
761   %27 = or i1 %22, %25
762   %28 = zext i1 %27 to i64
763   %29 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %12, i64 %3)
764   %30 = extractvalue { i64, i1 } %29, 1
765   %31 = extractvalue { i64, i1 } %29, 0
766   %32 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %31, i64 %28)
767   %33 = extractvalue { i64, i1 } %32, 1
768   %34 = extractvalue { i64, i1 } %32, 0
769   %35 = or i1 %30, %33
770   %36 = zext i1 %35 to i64
771   %37 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %14, i64 %4)
772   %38 = extractvalue { i64, i1 } %37, 1
773   %39 = extractvalue { i64, i1 } %37, 0
774   %40 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %39, i64 %36)
775   %41 = extractvalue { i64, i1 } %40, 1
776   %42 = extractvalue { i64, i1 } %40, 0
777   %43 = or i1 %38, %41
778   %44 = zext i1 %43 to i64
779   %45 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %16, i64 %5)
780   %46 = extractvalue { i64, i1 } %45, 1
781   %47 = extractvalue { i64, i1 } %45, 0
782   %48 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %47, i64 %44)
783   %49 = extractvalue { i64, i1 } %48, 1
784   %50 = extractvalue { i64, i1 } %48, 0
785   %51 = or i1 %46, %49
786   store i64 %19, i64* %7, align 8
787   store i64 %26, i64* %9, align 8
788   store i64 %34, i64* %11, align 8
789   store i64 %42, i64* %13, align 8
790   store i64 %50, i64* %15, align 8
791   %52 = zext i1 %51 to i32
792   ret i32 %52
795 %struct.U192 = type { [3 x i64] }
797 define void @PR39464(%struct.U192* noalias nocapture sret(%struct.U192) %0, %struct.U192* nocapture readonly dereferenceable(24) %1, %struct.U192* nocapture readonly dereferenceable(24) %2) {
798 ; CHECK-LABEL: PR39464:
799 ; CHECK:       # %bb.0:
800 ; CHECK-NEXT:    movq %rdi, %rax
801 ; CHECK-NEXT:    movq (%rsi), %rcx
802 ; CHECK-NEXT:    addq (%rdx), %rcx
803 ; CHECK-NEXT:    movq %rcx, (%rdi)
804 ; CHECK-NEXT:    movq 8(%rsi), %rcx
805 ; CHECK-NEXT:    adcq 8(%rdx), %rcx
806 ; CHECK-NEXT:    movq %rcx, 8(%rdi)
807 ; CHECK-NEXT:    movq 16(%rsi), %rcx
808 ; CHECK-NEXT:    adcq 16(%rdx), %rcx
809 ; CHECK-NEXT:    movq %rcx, 16(%rdi)
810 ; CHECK-NEXT:    retq
811   %4 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 0
812   %5 = load i64, i64* %4, align 8
813   %6 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 0
814   %7 = load i64, i64* %6, align 8
815   %8 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %5, i64 %7)
816   %9 = extractvalue { i64, i1 } %8, 1
817   %10 = extractvalue { i64, i1 } %8, 0
818   %11 = zext i1 %9 to i64
819   %12 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 0
820   store i64 %10, i64* %12, align 8
821   %13 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 1
822   %14 = load i64, i64* %13, align 8
823   %15 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 1
824   %16 = load i64, i64* %15, align 8
825   %17 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %14, i64 %16)
826   %18 = extractvalue { i64, i1 } %17, 1
827   %19 = extractvalue { i64, i1 } %17, 0
828   %20 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %19, i64 %11)
829   %21 = extractvalue { i64, i1 } %20, 1
830   %22 = extractvalue { i64, i1 } %20, 0
831   %23 = or i1 %18, %21
832   %24 = zext i1 %23 to i64
833   %25 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 1
834   store i64 %22, i64* %25, align 8
835   %26 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 2
836   %27 = load i64, i64* %26, align 8
837   %28 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 2
838   %29 = load i64, i64* %28, align 8
839   %30 = add i64 %27, %29
840   %31 = add i64 %30, %24
841   %32 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 2
842   store i64 %31, i64* %32, align 8
843   ret void
847 %uint128 = type { i64, i64 }
849 define zeroext i1 @uaddo_U128_without_i128_or(i64 %0, i64 %1, i64 %2, i64 %3, %uint128* nocapture %4) nounwind {
850 ; CHECK-LABEL: uaddo_U128_without_i128_or:
851 ; CHECK:       # %bb.0:
852 ; CHECK-NEXT:    addq %rdx, %rdi
853 ; CHECK-NEXT:    adcq %rcx, %rsi
854 ; CHECK-NEXT:    setb %al
855 ; CHECK-NEXT:    movq %rsi, (%r8)
856 ; CHECK-NEXT:    movq %rdi, 8(%r8)
857 ; CHECK-NEXT:    retq
858   %6 = add i64 %2, %0
859   %7 = icmp ult i64 %6, %0
860   %8 = add i64 %3, %1
861   %9 = icmp ult i64 %8, %1
862   %10 = zext i1 %7 to i64
863   %11 = add i64 %8, %10
864   %12 = icmp ult i64 %11, %8
865   %13 = or i1 %9, %12
866   %14 = getelementptr inbounds %uint128, %uint128* %4, i64 0, i32 0
867   store i64 %11, i64* %14, align 8
868   %15 = getelementptr inbounds %uint128, %uint128* %4, i64 0, i32 1
869   store i64 %6, i64* %15, align 8
870   ret i1 %13
874 %uint192 = type { i64, i64, i64 }
876 define void @add_U192_without_i128_or(%uint192* sret(%uint192) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6) nounwind {
877 ; CHECK-LABEL: add_U192_without_i128_or:
878 ; CHECK:       # %bb.0:
879 ; CHECK-NEXT:    movq %rdi, %rax
880 ; CHECK-NEXT:    addq %r8, %rsi
881 ; CHECK-NEXT:    adcq %r9, %rdx
882 ; CHECK-NEXT:    adcq {{[0-9]+}}(%rsp), %rcx
883 ; CHECK-NEXT:    movq %rcx, (%rdi)
884 ; CHECK-NEXT:    movq %rdx, 8(%rdi)
885 ; CHECK-NEXT:    movq %rsi, 16(%rdi)
886 ; CHECK-NEXT:    retq
887   %8 = add i64 %4, %1
888   %9 = icmp ult i64 %8, %1
889   %10 = add i64 %5, %2
890   %11 = icmp ult i64 %10, %2
891   %12 = zext i1 %9 to i64
892   %13 = add i64 %10, %12
893   %14 = icmp ult i64 %13, %10
894   %15 = or i1 %11, %14
895   %16 = add i64 %6, %3
896   %17 = zext i1 %15 to i64
897   %18 = add i64 %16, %17
898   %19 = getelementptr inbounds %uint192, %uint192* %0, i64 0, i32 0
899   store i64 %18, i64* %19, align 8
900   %20 = getelementptr inbounds %uint192, %uint192* %0, i64 0, i32 1
901   store i64 %13, i64* %20, align 8
902   %21 = getelementptr inbounds %uint192, %uint192* %0, i64 0, i32 2
903   store i64 %8, i64* %21, align 8
904   ret void
908 %uint256 = type { %uint128, %uint128 }
910 ; Classic unrolled 256-bit addition implementation using i64 as the word type.
911 ; It starts by adding least significant words and propagates carry to additions of the higher words.
912 define void @add_U256_without_i128_or_by_i64_words(%uint256* sret(%uint256) %0, %uint256* %1, %uint256* %2) nounwind {
913 ; CHECK-LABEL: add_U256_without_i128_or_by_i64_words:
914 ; CHECK:       # %bb.0:
915 ; CHECK-NEXT:    movq %rdi, %rax
916 ; CHECK-NEXT:    movq (%rdx), %r8
917 ; CHECK-NEXT:    movq 8(%rdx), %rdi
918 ; CHECK-NEXT:    addq (%rsi), %r8
919 ; CHECK-NEXT:    adcq 8(%rsi), %rdi
920 ; CHECK-NEXT:    movq 16(%rdx), %rcx
921 ; CHECK-NEXT:    adcq 16(%rsi), %rcx
922 ; CHECK-NEXT:    movq 24(%rdx), %rdx
923 ; CHECK-NEXT:    adcq 24(%rsi), %rdx
924 ; CHECK-NEXT:    movq %rdx, (%rax)
925 ; CHECK-NEXT:    movq %rcx, 8(%rax)
926 ; CHECK-NEXT:    movq %rdi, 16(%rax)
927 ; CHECK-NEXT:    movq %r8, 24(%rax)
928 ; CHECK-NEXT:    retq
929   %4 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 0, i32 0
930   %5 = load i64, i64* %4, align 8
931   %6 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 0, i32 0
932   %7 = load i64, i64* %6, align 8
933   %8 = add i64 %7, %5
934   %9 = icmp ult i64 %8, %5
935   %10 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 0, i32 1
936   %11 = load i64, i64* %10, align 8
937   %12 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 0, i32 1
938   %13 = load i64, i64* %12, align 8
939   %14 = add i64 %13, %11
940   %15 = icmp ult i64 %14, %11
941   %16 = zext i1 %9 to i64
942   %17 = add i64 %14, %16
943   %18 = icmp ult i64 %17, %16
944   %19 = or i1 %15, %18
945   %20 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 1, i32 0
946   %21 = load i64, i64* %20, align 8
947   %22 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 1, i32 0
948   %23 = load i64, i64* %22, align 8
949   %24 = add i64 %23, %21
950   %25 = icmp ult i64 %24, %21
951   %26 = zext i1 %19 to i64
952   %27 = add i64 %24, %26
953   %28 = icmp ult i64 %27, %26
954   %29 = or i1 %25, %28
955   %30 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 1, i32 1
956   %31 = load i64, i64* %30, align 8
957   %32 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 1, i32 1
958   %33 = load i64, i64* %32, align 8
959   %34 = add i64 %33, %31
960   %35 = zext i1 %29 to i64
961   %36 = add i64 %34, %35
962   %37 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 0, i32 0
963   store i64 %36, i64* %37, align 8
964   %38 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 0, i32 1
965   store i64 %27, i64* %38, align 8
966   %39 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 1, i32 0
967   store i64 %17, i64* %39, align 8
968   %40 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 1, i32 1
969   store i64 %8, i64* %40, align 8
970   ret void
973 ; The 256-bit addition implementation using two inlined uaddo procedures for U128 type { i64, i64 }.
974 ; This is similar to how LLVM legalize types in CodeGen.
975 define void @add_U256_without_i128_or_recursive(%uint256* sret(%uint256) %0, %uint256* %1, %uint256* %2) nounwind {
976 ; CHECK-LABEL: add_U256_without_i128_or_recursive:
977 ; CHECK:       # %bb.0:
978 ; CHECK-NEXT:    movq %rdi, %rax
979 ; CHECK-NEXT:    movq (%rdx), %r8
980 ; CHECK-NEXT:    movq 8(%rdx), %rdi
981 ; CHECK-NEXT:    addq (%rsi), %r8
982 ; CHECK-NEXT:    adcq 8(%rsi), %rdi
983 ; CHECK-NEXT:    movq 16(%rdx), %rcx
984 ; CHECK-NEXT:    movq 24(%rdx), %rdx
985 ; CHECK-NEXT:    adcq 16(%rsi), %rcx
986 ; CHECK-NEXT:    adcq 24(%rsi), %rdx
987 ; CHECK-NEXT:    movq %r8, (%rax)
988 ; CHECK-NEXT:    movq %rdi, 8(%rax)
989 ; CHECK-NEXT:    movq %rcx, 16(%rax)
990 ; CHECK-NEXT:    movq %rdx, 24(%rax)
991 ; CHECK-NEXT:    retq
992   %4 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 0, i32 0
993   %5 = load i64, i64* %4, align 8
994   %6 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 0, i32 1
995   %7 = load i64, i64* %6, align 8
996   %8 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 0, i32 0
997   %9 = load i64, i64* %8, align 8
998   %10 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 0, i32 1
999   %11 = load i64, i64* %10, align 8
1000   %12 = add i64 %9, %5
1001   %13 = icmp ult i64 %12, %5
1002   %14 = add i64 %11, %7
1003   %15 = icmp ult i64 %14, %7
1004   %16 = zext i1 %13 to i64
1005   %17 = add i64 %14, %16
1006   %18 = icmp ult i64 %17, %14
1007   %19 = or i1 %15, %18
1008   %20 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 1, i32 0
1009   %21 = load i64, i64* %20, align 8
1010   %22 = getelementptr inbounds %uint256, %uint256* %1, i64 0, i32 1, i32 1
1011   %23 = load i64, i64* %22, align 8
1012   %24 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 1, i32 0
1013   %25 = load i64, i64* %24, align 8
1014   %26 = getelementptr inbounds %uint256, %uint256* %2, i64 0, i32 1, i32 1
1015   %27 = load i64, i64* %26, align 8
1016   %28 = add i64 %25, %21
1017   %29 = icmp ult i64 %28, %21
1018   %30 = add i64 %27, %23
1019   %31 = zext i1 %29 to i64
1020   %32 = add i64 %30, %31
1021   %33 = zext i1 %19 to i64
1022   %34 = add i64 %28, %33
1023   %35 = icmp ult i64 %34, %28
1024   %36 = zext i1 %35 to i64
1025   %37 = add i64 %32, %36
1026   %38 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 0, i32 0
1027   store i64 %12, i64* %38, align 8
1028   %39 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 0, i32 1
1029   store i64 %17, i64* %39, align 8
1030   %40 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 1, i32 0
1031   store i64 %34, i64* %40, align 8
1032   %41 = getelementptr inbounds %uint256, %uint256* %0, i64 0, i32 1, i32 1
1033   store i64 %37, i64* %41, align 8
1034   ret void