1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
3
4declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)
5declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #1
6
7define 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
15entry:
16  %0 = add i128 %a, %b
17  ret i128 %0
18}
19
20define 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
26entry:
27  %0 = load i128, i128* %a
28  %1 = add i128 %0, %b
29  store i128 %1, i128* %a
30  ret void
31}
32
33define 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
39entry:
40  %0 = load i128, i128* %b
41  %1 = add i128 %a, %0
42  store i128 %1, i128* %b
43  ret void
44}
45
46define 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
59entry:
60  %0 = add i256 %a, %b
61  ret i256 %0
62}
63
64define 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
72entry:
73  %0 = load i256, i256* %a
74  %1 = add i256 %0, %b
75  store i256 %1, i256* %a
76  ret void
77}
78
79define 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
87entry:
88  %0 = load i256, i256* %b
89  %1 = add i256 %a, %0
90  store i256 %1, i256* %b
91  ret void
92}
93
94define 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
102entry:
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
115}
116
117define 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
124entry:
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
134}
135
136define 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
143entry:
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
153}
154
155define 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
162entry:
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
172}
173
174define 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
196}
197
198%scalar = type { [4 x i64] }
199
200define %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
213entry:
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
255}
256
257%accumulator= type { i64, i64, i32 }
258
259define 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
268entry:
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
293}
294
295define 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
302entry:
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
311}
312
313%S = type { [4 x i64] }
314
315define %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
336entry:
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
378}
379
380define 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
391}
392
393define 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
416}
417
418%struct.U320 = type { [5 x i64] }
419
420define 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
509}
510
511define 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
565}
566
567define 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
621}
622
623; Either the primary addition can overflow or the addition of the carry, but
624; they cannot both overflow.
625define 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
678}
679
680define 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
728}
729
730define 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
793}
794
795%struct.U192 = type { [3 x i64] }
796
797define 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
844}
845
846
847%uint128 = type { i64, i64 }
848
849define 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
871}
872
873
874%uint192 = type { i64, i64, i64 }
875
876define 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
905}
906
907
908%uint256 = type { %uint128, %uint128 }
909
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.
912define 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
971}
972
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.
975define 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
1035}
1036