[X86] Add more add/sub carry tests

Preparation for: https://reviews.llvm.org/D70079

https://reviews.llvm.org/D70077
This commit is contained in:
David Zarzycki 2019-11-11 15:07:51 +02:00
parent a75f8d98d7
commit a9018fddf9
4 changed files with 622 additions and 3 deletions

View File

@ -199,7 +199,7 @@ define zeroext i1 @f10(i64 %src, i64 %index, i64 %a, i64 *%res) {
define zeroext i1 @f11(i32 *%ptr0) {
; CHECK-LABEL: f11:
; CHECK: brasl %r14, foo@PLT
; CHECK: algf %r2, 160(%r15)
; CHECK: algf {{%r[0-9]+}}, 160(%r15)
; CHECK: br %r14
%ptr1 = getelementptr i32, i32 *%ptr0, i64 2
%ptr2 = getelementptr i32, i32 *%ptr0, i64 4

View File

@ -207,7 +207,7 @@ define zeroext i1 @f10(i64 %src, i64 %index, i64 %a, i64 *%res) {
define zeroext i1 @f11(i32 *%ptr0) {
; CHECK-LABEL: f11:
; CHECK: brasl %r14, foo@PLT
; CHECK: slgf %r2, 160(%r15)
; CHECK: slgf {{%r[0-9]+}}, 160(%r15)
; CHECK: br %r14
%ptr1 = getelementptr i32, i32 *%ptr0, i64 2
%ptr2 = getelementptr i32, i32 *%ptr0, i64 4

View File

@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #1
define i128 @add128(i128 %a, i128 %b) nounwind {
; CHECK-LABEL: add128:
; CHECK: # %bb.0: # %entry
@ -411,3 +413,419 @@ define i128 @addcarry_to_subcarry(i64 %a, i64 %b) {
%sub2 = add i128 %sum2, %notb128
ret i128 %sub2
}
%struct.U320 = type { [5 x i64] }
define i32 @add_U320_without_i128_add(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: add_U320_without_i128_add:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: movq 16(%rdi), %rax
; CHECK-NEXT: leaq (%rax,%rcx), %r10
; CHECK-NEXT: addq %rsi, (%rdi)
; CHECK-NEXT: adcq %rdx, 8(%rdi)
; CHECK-NEXT: movq %rax, %rdx
; CHECK-NEXT: adcq %rcx, %rdx
; CHECK-NEXT: movq 24(%rdi), %r11
; CHECK-NEXT: leaq (%r8,%r11), %r14
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: cmpq %r10, %rdx
; CHECK-NEXT: setb %bl
; CHECK-NEXT: addq %rcx, %rax
; CHECK-NEXT: adcq %r14, %rbx
; CHECK-NEXT: movq 32(%rdi), %r10
; CHECK-NEXT: leaq (%r9,%r10), %rcx
; CHECK-NEXT: xorl %esi, %esi
; CHECK-NEXT: cmpq %r14, %rbx
; CHECK-NEXT: setb %sil
; CHECK-NEXT: addq %r11, %r8
; CHECK-NEXT: adcq %rcx, %rsi
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: cmpq %rcx, %rsi
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq %r10, %r9
; CHECK-NEXT: movq %rdx, 16(%rdi)
; CHECK-NEXT: movq %rbx, 24(%rdi)
; CHECK-NEXT: movq %rsi, 32(%rdi)
; CHECK-NEXT: adcl $0, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = add i64 %8, %1
%18 = add i64 %10, %2
%19 = icmp ult i64 %17, %1
%20 = zext i1 %19 to i64
%21 = add i64 %18, %20
%22 = add i64 %12, %3
%23 = icmp ult i64 %18, %10
%24 = zext i1 %23 to i64
%25 = icmp ult i64 %21, %18
%26 = zext i1 %25 to i64
%27 = add i64 %22, %24
%28 = add i64 %27, %26
%29 = add i64 %14, %4
%30 = icmp ult i64 %22, %12
%31 = zext i1 %30 to i64
%32 = icmp ult i64 %28, %22
%33 = zext i1 %32 to i64
%34 = add i64 %29, %31
%35 = add i64 %34, %33
%36 = add i64 %16, %5
%37 = icmp ult i64 %29, %14
%38 = zext i1 %37 to i64
%39 = icmp ult i64 %35, %29
%40 = zext i1 %39 to i64
%41 = add i64 %36, %38
%42 = add i64 %41, %40
store i64 %17, i64* %7, align 8
store i64 %21, i64* %9, align 8
store i64 %28, i64* %11, align 8
store i64 %35, i64* %13, align 8
store i64 %42, i64* %15, align 8
%43 = icmp ult i64 %36, %16
%44 = zext i1 %43 to i32
%45 = icmp ult i64 %42, %36
%46 = zext i1 %45 to i32
%47 = add nuw nsw i32 %46, %44
ret i32 %47
}
define i32 @add_U320_without_i128_or(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: add_U320_without_i128_or:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: addq 8(%rdi), %rdx
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, (%rdi)
; CHECK-NEXT: adcq $0, %rdx
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 16(%rdi), %rcx
; CHECK-NEXT: setb %r11b
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %ebx
; CHECK-NEXT: addq %rcx, %rbx
; CHECK-NEXT: setb %cl
; CHECK-NEXT: addq 24(%rdi), %r8
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: orb %r11b, %cl
; CHECK-NEXT: movzbl %cl, %esi
; CHECK-NEXT: addq %r8, %rsi
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 32(%rdi), %r9
; CHECK-NEXT: setb %r8b
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: addq %r9, %rax
; CHECK-NEXT: setb %cl
; CHECK-NEXT: movq %rdx, 8(%rdi)
; CHECK-NEXT: movq %rbx, 16(%rdi)
; CHECK-NEXT: movq %rsi, 24(%rdi)
; CHECK-NEXT: movq %rax, 32(%rdi)
; CHECK-NEXT: orb %r8b, %cl
; CHECK-NEXT: movzbl %cl, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = add i64 %8, %1
%18 = add i64 %10, %2
%19 = icmp ult i64 %17, %1
%20 = zext i1 %19 to i64
%21 = add i64 %18, %20
%22 = add i64 %12, %3
%23 = icmp ult i64 %18, %10
%24 = icmp ult i64 %21, %18
%25 = or i1 %23, %24
%26 = zext i1 %25 to i64
%27 = add i64 %22, %26
%28 = add i64 %14, %4
%29 = icmp ult i64 %22, %12
%30 = icmp ult i64 %27, %22
%31 = or i1 %29, %30
%32 = zext i1 %31 to i64
%33 = add i64 %28, %32
%34 = add i64 %16, %5
%35 = icmp ult i64 %28, %14
%36 = icmp ult i64 %33, %28
%37 = or i1 %35, %36
%38 = zext i1 %37 to i64
%39 = add i64 %34, %38
store i64 %17, i64* %7, align 8
store i64 %21, i64* %9, align 8
store i64 %27, i64* %11, align 8
store i64 %33, i64* %13, align 8
store i64 %39, i64* %15, align 8
%40 = icmp ult i64 %34, %16
%41 = icmp ult i64 %39, %34
%42 = or i1 %40, %41
%43 = zext i1 %42 to i32
ret i32 %43
}
define i32 @add_U320_without_i128_xor(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: add_U320_without_i128_xor:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: addq 8(%rdi), %rdx
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, (%rdi)
; CHECK-NEXT: adcq $0, %rdx
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 16(%rdi), %rcx
; CHECK-NEXT: setb %r11b
; CHECK-NEXT: xorb %r10b, %al
; CHECK-NEXT: movzbl %al, %ebx
; CHECK-NEXT: addq %rcx, %rbx
; CHECK-NEXT: setb %cl
; CHECK-NEXT: addq 24(%rdi), %r8
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: xorb %r11b, %cl
; CHECK-NEXT: movzbl %cl, %esi
; CHECK-NEXT: addq %r8, %rsi
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 32(%rdi), %r9
; CHECK-NEXT: setb %r8b
; CHECK-NEXT: xorb %r10b, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: addq %r9, %rax
; CHECK-NEXT: setb %cl
; CHECK-NEXT: movq %rdx, 8(%rdi)
; CHECK-NEXT: movq %rbx, 16(%rdi)
; CHECK-NEXT: movq %rsi, 24(%rdi)
; CHECK-NEXT: movq %rax, 32(%rdi)
; CHECK-NEXT: xorb %r8b, %cl
; CHECK-NEXT: movzbl %cl, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = add i64 %8, %1
%18 = add i64 %10, %2
%19 = icmp ult i64 %17, %1
%20 = zext i1 %19 to i64
%21 = add i64 %18, %20
%22 = add i64 %12, %3
%23 = icmp ult i64 %18, %10
%24 = icmp ult i64 %21, %18
%25 = xor i1 %23, %24
%26 = zext i1 %25 to i64
%27 = add i64 %22, %26
%28 = add i64 %14, %4
%29 = icmp ult i64 %22, %12
%30 = icmp ult i64 %27, %22
%31 = xor i1 %29, %30
%32 = zext i1 %31 to i64
%33 = add i64 %28, %32
%34 = add i64 %16, %5
%35 = icmp ult i64 %28, %14
%36 = icmp ult i64 %33, %28
%37 = xor i1 %35, %36
%38 = zext i1 %37 to i64
%39 = add i64 %34, %38
store i64 %17, i64* %7, align 8
store i64 %21, i64* %9, align 8
store i64 %27, i64* %11, align 8
store i64 %33, i64* %13, align 8
store i64 %39, i64* %15, align 8
%40 = icmp ult i64 %34, %16
%41 = icmp ult i64 %39, %34
%42 = xor i1 %40, %41
%43 = zext i1 %42 to i32
ret i32 %43
}
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) {
; CHECK-LABEL: add_U320_without_i128_or_no_ret:
; CHECK: # %bb.0:
; CHECK-NEXT: addq 8(%rdi), %rdx
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, (%rdi)
; CHECK-NEXT: adcq $0, %rdx
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 16(%rdi), %rcx
; CHECK-NEXT: setb %r11b
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %esi
; CHECK-NEXT: addq %rcx, %rsi
; CHECK-NEXT: setb %cl
; CHECK-NEXT: addq 24(%rdi), %r8
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: orb %r11b, %cl
; CHECK-NEXT: movzbl %cl, %ecx
; CHECK-NEXT: addq %r8, %rcx
; CHECK-NEXT: setb %al
; CHECK-NEXT: addq 32(%rdi), %r9
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: addq %r9, %rax
; CHECK-NEXT: movq %rdx, 8(%rdi)
; CHECK-NEXT: movq %rsi, 16(%rdi)
; CHECK-NEXT: movq %rcx, 24(%rdi)
; CHECK-NEXT: movq %rax, 32(%rdi)
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = add i64 %8, %1
%18 = add i64 %10, %2
%19 = icmp ult i64 %17, %1
%20 = zext i1 %19 to i64
%21 = add i64 %18, %20
%22 = add i64 %12, %3
%23 = icmp ult i64 %18, %10
%24 = icmp ult i64 %21, %18
%25 = or i1 %23, %24
%26 = zext i1 %25 to i64
%27 = add i64 %22, %26
%28 = add i64 %14, %4
%29 = icmp ult i64 %22, %12
%30 = icmp ult i64 %27, %22
%31 = or i1 %29, %30
%32 = zext i1 %31 to i64
%33 = add i64 %28, %32
%34 = add i64 %16, %5
%35 = icmp ult i64 %28, %14
%36 = icmp ult i64 %33, %28
%37 = or i1 %35, %36
%38 = zext i1 %37 to i64
%39 = add i64 %34, %38
store i64 %17, i64* %7, align 8
store i64 %21, i64* %9, align 8
store i64 %27, i64* %11, align 8
store i64 %33, i64* %13, align 8
store i64 %39, i64* %15, align 8
ret void
}
define i32 @add_U320_uaddo(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: add_U320_uaddo:
; CHECK: # %bb.0:
; CHECK-NEXT: addq 8(%rdi), %rdx
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, (%rdi)
; CHECK-NEXT: adcq $0, %rdx
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %esi
; CHECK-NEXT: addq 16(%rdi), %rcx
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, %rcx
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %esi
; CHECK-NEXT: addq 24(%rdi), %r8
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, %r8
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movzbl %al, %esi
; CHECK-NEXT: addq 32(%rdi), %r9
; CHECK-NEXT: setb %r10b
; CHECK-NEXT: addq %rsi, %r9
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %r10b, %al
; CHECK-NEXT: movq %rdx, 8(%rdi)
; CHECK-NEXT: movq %rcx, 16(%rdi)
; CHECK-NEXT: movq %r8, 24(%rdi)
; CHECK-NEXT: movq %r9, 32(%rdi)
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %8, i64 %1)
%18 = extractvalue { i64, i1 } %17, 1
%19 = extractvalue { i64, i1 } %17, 0
%20 = zext i1 %18 to i64
%21 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %10, i64 %2)
%22 = extractvalue { i64, i1 } %21, 1
%23 = extractvalue { i64, i1 } %21, 0
%24 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %23, i64 %20)
%25 = extractvalue { i64, i1 } %24, 1
%26 = extractvalue { i64, i1 } %24, 0
%27 = or i1 %22, %25
%28 = zext i1 %27 to i64
%29 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %12, i64 %3)
%30 = extractvalue { i64, i1 } %29, 1
%31 = extractvalue { i64, i1 } %29, 0
%32 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %31, i64 %28)
%33 = extractvalue { i64, i1 } %32, 1
%34 = extractvalue { i64, i1 } %32, 0
%35 = or i1 %30, %33
%36 = zext i1 %35 to i64
%37 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %14, i64 %4)
%38 = extractvalue { i64, i1 } %37, 1
%39 = extractvalue { i64, i1 } %37, 0
%40 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %39, i64 %36)
%41 = extractvalue { i64, i1 } %40, 1
%42 = extractvalue { i64, i1 } %40, 0
%43 = or i1 %38, %41
%44 = zext i1 %43 to i64
%45 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %16, i64 %5)
%46 = extractvalue { i64, i1 } %45, 1
%47 = extractvalue { i64, i1 } %45, 0
%48 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %47, i64 %44)
%49 = extractvalue { i64, i1 } %48, 1
%50 = extractvalue { i64, i1 } %48, 0
%51 = or i1 %46, %49
store i64 %19, i64* %7, align 8
store i64 %26, i64* %9, align 8
store i64 %34, i64* %11, align 8
store i64 %42, i64* %13, align 8
store i64 %50, i64* %15, align 8
%52 = zext i1 %51 to i32
ret i32 %52
}

View File

@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) #1
define i128 @sub128(i128 %a, i128 %b) nounwind {
; CHECK-LABEL: sub128:
; CHECK: # %bb.0: # %entry
@ -87,7 +89,7 @@ entry:
ret %S %31
}
define %S @sub(%S* nocapture readonly %this, %S %arg.b) local_unnamed_addr {
define %S @sub(%S* nocapture readonly %this, %S %arg.b) {
; CHECK-LABEL: sub:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
@ -183,3 +185,202 @@ define i64 @sub_from_carry(i64 %x, i64 %y, i64* %valout, i64 %z) {
%res = sub i64 %carry, %z
ret i64 %res
}
%struct.U320 = type { [5 x i64] }
define i32 @sub_U320_without_i128_or(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: sub_U320_without_i128_or:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: movq 8(%rdi), %r14
; CHECK-NEXT: movq 16(%rdi), %r10
; CHECK-NEXT: movq 24(%rdi), %r11
; CHECK-NEXT: movq 32(%rdi), %rbx
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: subq %rsi, (%rdi)
; CHECK-NEXT: setb %al
; CHECK-NEXT: subq %rdx, %r14
; CHECK-NEXT: setb %dl
; CHECK-NEXT: subq %rax, %r14
; CHECK-NEXT: setb %al
; CHECK-NEXT: subq %rcx, %r10
; CHECK-NEXT: setb %cl
; CHECK-NEXT: orb %dl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %rax, %r10
; CHECK-NEXT: setb %al
; CHECK-NEXT: subq %r8, %r11
; CHECK-NEXT: setb %dl
; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %rax, %r11
; CHECK-NEXT: setb %al
; CHECK-NEXT: subq %r9, %rbx
; CHECK-NEXT: setb %cl
; CHECK-NEXT: orb %dl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %rax, %rbx
; CHECK-NEXT: setb %al
; CHECK-NEXT: movq %r14, 8(%rdi)
; CHECK-NEXT: movq %r10, 16(%rdi)
; CHECK-NEXT: movq %r11, 24(%rdi)
; CHECK-NEXT: movq %rbx, 32(%rdi)
; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = sub i64 %8, %1
%18 = sub i64 %10, %2
%19 = icmp ult i64 %8, %1
%20 = zext i1 %19 to i64
%21 = sub i64 %18, %20
%22 = sub i64 %12, %3
%23 = icmp ult i64 %10, %2
%24 = icmp ult i64 %18, %20
%25 = or i1 %23, %24
%26 = zext i1 %25 to i64
%27 = sub i64 %22, %26
%28 = sub i64 %14, %4
%29 = icmp ult i64 %12, %3
%30 = icmp ult i64 %22, %26
%31 = or i1 %29, %30
%32 = zext i1 %31 to i64
%33 = sub i64 %28, %32
%34 = sub i64 %16, %5
%35 = icmp ult i64 %14, %4
%36 = icmp ult i64 %28, %32
%37 = or i1 %35, %36
%38 = zext i1 %37 to i64
%39 = sub i64 %34, %38
store i64 %17, i64* %7, align 8
store i64 %21, i64* %9, align 8
store i64 %27, i64* %11, align 8
store i64 %33, i64* %13, align 8
store i64 %39, i64* %15, align 8
%40 = icmp ult i64 %16, %5
%41 = icmp ult i64 %34, %38
%42 = or i1 %40, %41
%43 = zext i1 %42 to i32
ret i32 %43
}
define i32 @sub_U320_usubo(%struct.U320* nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
; CHECK-LABEL: sub_U320_usubo:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: movq 8(%rdi), %r14
; CHECK-NEXT: movq 16(%rdi), %r10
; CHECK-NEXT: movq 24(%rdi), %r11
; CHECK-NEXT: movq 32(%rdi), %rbx
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: subq %rsi, (%rdi)
; CHECK-NEXT: setb %al
; CHECK-NEXT: subq %rdx, %r14
; CHECK-NEXT: setb %dl
; CHECK-NEXT: subq %rax, %r14
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %dl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %rcx, %r10
; CHECK-NEXT: setb %cl
; CHECK-NEXT: subq %rax, %r10
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %r8, %r11
; CHECK-NEXT: setb %cl
; CHECK-NEXT: subq %rax, %r11
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: subq %r9, %rbx
; CHECK-NEXT: setb %cl
; CHECK-NEXT: subq %rax, %rbx
; CHECK-NEXT: setb %al
; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: movq %r14, 8(%rdi)
; CHECK-NEXT: movq %r10, 16(%rdi)
; CHECK-NEXT: movq %r11, 24(%rdi)
; CHECK-NEXT: movq %rbx, 32(%rdi)
; CHECK-NEXT: movzbl %al, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%7 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 0
%8 = load i64, i64* %7, align 8
%9 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 2
%12 = load i64, i64* %11, align 8
%13 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 3
%14 = load i64, i64* %13, align 8
%15 = getelementptr inbounds %struct.U320, %struct.U320* %0, i64 0, i32 0, i64 4
%16 = load i64, i64* %15, align 8
%17 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %8, i64 %1)
%18 = extractvalue { i64, i1 } %17, 1
%19 = extractvalue { i64, i1 } %17, 0
%20 = zext i1 %18 to i64
%21 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %10, i64 %2)
%22 = extractvalue { i64, i1 } %21, 1
%23 = extractvalue { i64, i1 } %21, 0
%24 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %23, i64 %20)
%25 = extractvalue { i64, i1 } %24, 1
%26 = extractvalue { i64, i1 } %24, 0
%27 = or i1 %22, %25
%28 = zext i1 %27 to i64
%29 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %12, i64 %3)
%30 = extractvalue { i64, i1 } %29, 1
%31 = extractvalue { i64, i1 } %29, 0
%32 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %31, i64 %28)
%33 = extractvalue { i64, i1 } %32, 1
%34 = extractvalue { i64, i1 } %32, 0
%35 = or i1 %30, %33
%36 = zext i1 %35 to i64
%37 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %14, i64 %4)
%38 = extractvalue { i64, i1 } %37, 1
%39 = extractvalue { i64, i1 } %37, 0
%40 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %39, i64 %36)
%41 = extractvalue { i64, i1 } %40, 1
%42 = extractvalue { i64, i1 } %40, 0
%43 = or i1 %38, %41
%44 = zext i1 %43 to i64
%45 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %16, i64 %5)
%46 = extractvalue { i64, i1 } %45, 1
%47 = extractvalue { i64, i1 } %45, 0
%48 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %47, i64 %44)
%49 = extractvalue { i64, i1 } %48, 1
%50 = extractvalue { i64, i1 } %48, 0
%51 = or i1 %46, %49
store i64 %19, i64* %7, align 8
store i64 %26, i64* %9, align 8
store i64 %34, i64* %11, align 8
store i64 %42, i64* %13, align 8
store i64 %50, i64* %15, align 8
%52 = zext i1 %51 to i32
ret i32 %52
}