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 {
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
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)
27 %0 = load i128, i128* %a
29 store i128 %1, i128* %a
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)
40 %0 = load i128, i128* %b
42 store i128 %1, i128* %b
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)
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)
73 %0 = load i256, i256* %a
75 store i256 %1, i256* %a
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)
88 %0 = load i256, i256* %b
90 store i256 %1, i256* %b
94 define void @a(i64* nocapture %s, i64* nocapture %t, i64 %a, i64 %b, i64 %c) nounwind {
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)
103 %0 = zext i64 %a to i128
104 %1 = zext i64 %b to i128
106 %3 = zext i64 %c to i128
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
117 define void @b(i32* nocapture %r, i64 %a, i64 %b, i32 %c) nounwind {
119 ; CHECK: # %bb.0: # %entry
120 ; CHECK-NEXT: addq %rdx, %rsi
121 ; CHECK-NEXT: adcl $0, %ecx
122 ; CHECK-NEXT: movl %ecx, (%rdi)
125 %0 = zext i64 %a to i128
126 %1 = zext i64 %b to i128
127 %2 = zext i32 %c to i128
129 %4 = lshr i128 %3, 64
131 %6 = trunc i128 %5 to i32
132 store i32 %6, i32* %r, align 4
136 define void @c(i16* nocapture %r, i64 %a, i64 %b, i16 %c) nounwind {
138 ; CHECK: # %bb.0: # %entry
139 ; CHECK-NEXT: addq %rdx, %rsi
140 ; CHECK-NEXT: adcw $0, %cx
141 ; CHECK-NEXT: movw %cx, (%rdi)
144 %0 = zext i64 %a to i128
145 %1 = zext i64 %b to i128
146 %2 = zext i16 %c to i128
148 %4 = lshr i128 %3, 64
150 %6 = trunc i128 %5 to i16
151 store i16 %6, i16* %r, align 4
155 define void @d(i8* nocapture %r, i64 %a, i64 %b, i8 %c) nounwind {
157 ; CHECK: # %bb.0: # %entry
158 ; CHECK-NEXT: addq %rdx, %rsi
159 ; CHECK-NEXT: adcb $0, %cl
160 ; CHECK-NEXT: movb %cl, (%rdi)
163 %0 = zext i64 %a to i128
164 %1 = zext i64 %b to i128
165 %2 = zext i8 %c to i128
167 %4 = lshr i128 %3, 64
169 %6 = trunc i128 %5 to i8
170 store i8 %6, i8* %r, align 4
174 define i8 @e(i32* nocapture %a, i32 %b) nounwind {
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
186 %1 = load i32, i32* %a, align 4
188 %3 = icmp ult i32 %2, %b
189 %4 = zext i1 %3 to i8
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
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)
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
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)
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
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
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
303 %0 = zext i64 %a to i128
304 %1 = zext i64 %b to i128
306 %3 = lshr i128 %2, 64
307 %4 = trunc i128 %3 to i64
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)
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
380 define i128 @addcarry1_not(i128 %n) {
381 ; CHECK-LABEL: addcarry1_not:
383 ; CHECK-NEXT: movq %rdi, %rax
384 ; CHECK-NEXT: xorl %edx, %edx
385 ; CHECK-NEXT: negq %rax
386 ; CHECK-NEXT: sbbq %rsi, %rdx
393 define i128 @addcarry_to_subcarry(i64 %a, i64 %b) {
394 ; CHECK-LABEL: addcarry_to_subcarry:
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
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
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:
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
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
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
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:
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
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
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
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
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
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
563 %43 = zext i1 %42 to i32
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:
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
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
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
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:
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
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
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
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:
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)
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
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
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
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
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
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:
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
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
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
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
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
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
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:
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)
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
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
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:
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)
859 %7 = icmp ult i64 %6, %0
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
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
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:
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)
888 %9 = icmp ult i64 %8, %1
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
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
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:
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)
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
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
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
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
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:
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)
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