1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s 3 4%"struct.std::array" = type { [4 x i64] } 5 6define void @PR47857(ptr noalias nocapture writeonly sret(%"struct.std::array") align 8 %0, ptr nocapture noundef nonnull readonly align 8 dereferenceable(32) %1, ptr nocapture noundef nonnull readonly align 8 dereferenceable(32) %2) { 7; CHECK-LABEL: PR47857: 8; CHECK: # %bb.0: 9; CHECK-NEXT: movq %rdi, %rax 10; CHECK-NEXT: movq (%rdx), %r9 11; CHECK-NEXT: movq 8(%rdx), %rcx 12; CHECK-NEXT: xorl %edi, %edi 13; CHECK-NEXT: addq (%rsi), %r9 14; CHECK-NEXT: adcq 8(%rsi), %rcx 15; CHECK-NEXT: movq 16(%rdx), %r8 16; CHECK-NEXT: adcq 16(%rsi), %r8 17; CHECK-NEXT: movq 24(%rdx), %rdx 18; CHECK-NEXT: adcq 24(%rsi), %rdx 19; CHECK-NEXT: sbbq %rdi, %rdi 20; CHECK-NEXT: andl $38, %edi 21; CHECK-NEXT: addq %rdi, %r9 22; CHECK-NEXT: adcq $0, %rcx 23; CHECK-NEXT: adcq $0, %r8 24; CHECK-NEXT: adcq $0, %rdx 25; CHECK-NEXT: sbbq %rdi, %rdi 26; CHECK-NEXT: andl $38, %edi 27; CHECK-NEXT: addq %r9, %rdi 28; CHECK-NEXT: adcq $0, %rcx 29; CHECK-NEXT: adcq $0, %r8 30; CHECK-NEXT: adcq $0, %rdx 31; CHECK-NEXT: movq %rdi, (%rax) 32; CHECK-NEXT: movq %rcx, 8(%rax) 33; CHECK-NEXT: movq %r8, 16(%rax) 34; CHECK-NEXT: movq %rdx, 24(%rax) 35; CHECK-NEXT: retq 36 %4 = load i64, ptr %1, align 8 37 %5 = getelementptr inbounds %"struct.std::array", ptr %1, i64 0, i32 0, i64 1 38 %6 = load i64, ptr %5, align 8 39 %7 = getelementptr inbounds %"struct.std::array", ptr %1, i64 0, i32 0, i64 2 40 %8 = load i64, ptr %7, align 8 41 %9 = getelementptr inbounds %"struct.std::array", ptr %1, i64 0, i32 0, i64 3 42 %10 = load i64, ptr %9, align 8 43 %11 = load i64, ptr %2, align 8 44 %12 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %11, i64 %4) 45 %13 = extractvalue { i64, i1 } %12, 0 46 %14 = extractvalue { i64, i1 } %12, 1 47 %15 = getelementptr inbounds %"struct.std::array", ptr %2, i64 0, i32 0, i64 1 48 %16 = load i64, ptr %15, align 8 49 %17 = zext i1 %14 to i8 50 %18 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %17, i64 %16, i64 %6) 51 %19 = extractvalue { i8, i64 } %18, 1 52 %20 = extractvalue { i8, i64 } %18, 0 53 %21 = icmp ne i8 %20, 0 54 %22 = getelementptr inbounds %"struct.std::array", ptr %2, i64 0, i32 0, i64 2 55 %23 = load i64, ptr %22, align 8 56 %24 = zext i1 %21 to i8 57 %25 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %24, i64 %23, i64 %8) 58 %26 = extractvalue { i8, i64 } %25, 1 59 %27 = extractvalue { i8, i64 } %25, 0 60 %28 = icmp ne i8 %27, 0 61 %29 = getelementptr inbounds %"struct.std::array", ptr %2, i64 0, i32 0, i64 3 62 %30 = load i64, ptr %29, align 8 63 %31 = zext i1 %28 to i8 64 %32 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %31, i64 %30, i64 %10) 65 %33 = extractvalue { i8, i64 } %32, 1 66 %34 = extractvalue { i8, i64 } %32, 0 67 %35 = icmp ne i8 %34, 0 68 %36 = zext i1 %35 to i8 69 %37 = tail call { i8, i64 } @llvm.x86.subborrow.64(i8 %36, i64 0, i64 0) 70 %38 = extractvalue { i8, i64 } %37, 1 71 %39 = and i64 %38, 38 72 %40 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %39, i64 %13) 73 %41 = extractvalue { i64, i1 } %40, 0 74 %42 = extractvalue { i64, i1 } %40, 1 75 %43 = zext i1 %42 to i8 76 %44 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %43, i64 0, i64 %19) 77 %45 = extractvalue { i8, i64 } %44, 1 78 %46 = extractvalue { i8, i64 } %44, 0 79 %47 = icmp ne i8 %46, 0 80 %48 = zext i1 %47 to i8 81 %49 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %48, i64 0, i64 %26) 82 %50 = extractvalue { i8, i64 } %49, 1 83 %51 = extractvalue { i8, i64 } %49, 0 84 %52 = icmp ne i8 %51, 0 85 %53 = zext i1 %52 to i8 86 %54 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %53, i64 0, i64 %33) 87 %55 = extractvalue { i8, i64 } %54, 1 88 %56 = extractvalue { i8, i64 } %54, 0 89 %57 = icmp ne i8 %56, 0 90 %58 = zext i1 %57 to i8 91 %59 = tail call { i8, i64 } @llvm.x86.subborrow.64(i8 %58, i64 %39, i64 %39) 92 %60 = extractvalue { i8, i64 } %59, 1 93 %61 = and i64 %60, 38 94 %62 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %61, i64 %41) 95 %63 = extractvalue { i64, i1 } %62, 0 96 %64 = extractvalue { i64, i1 } %62, 1 97 %65 = zext i1 %64 to i8 98 %66 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %65, i64 0, i64 %45) 99 %67 = extractvalue { i8, i64 } %66, 1 100 %68 = extractvalue { i8, i64 } %66, 0 101 %69 = icmp ne i8 %68, 0 102 %70 = zext i1 %69 to i8 103 %71 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %70, i64 0, i64 %50) 104 %72 = extractvalue { i8, i64 } %71, 1 105 %73 = extractvalue { i8, i64 } %71, 0 106 %74 = icmp ne i8 %73, 0 107 %75 = zext i1 %74 to i8 108 %76 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %75, i64 0, i64 %55) 109 %77 = extractvalue { i8, i64 } %76, 1 110 store i64 %63, ptr %0, align 8 111 %78 = getelementptr inbounds %"struct.std::array", ptr %0, i64 0, i32 0, i64 1 112 store i64 %67, ptr %78, align 8 113 %79 = getelementptr inbounds %"struct.std::array", ptr %0, i64 0, i32 0, i64 2 114 store i64 %72, ptr %79, align 8 115 %80 = getelementptr inbounds %"struct.std::array", ptr %0, i64 0, i32 0, i64 3 116 store i64 %77, ptr %80, align 8 117 ret void 118} 119declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64) 120declare { i8, i64 } @llvm.x86.subborrow.64(i8, i64, i64) 121declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) 122