1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s 3%0 = type { i64, i64 } 4%1 = type { i128, i1 } 5 6; This used to call muloti4, but that won't link with libgcc. 7define %0 @x(i64 %a.coerce0, i64 %a.coerce1, i64 %b.coerce0, i64 %b.coerce1) nounwind uwtable ssp { 8; CHECK-LABEL: x: 9; CHECK: ## %bb.0: ## %entry 10; CHECK-NEXT: pushq %r14 11; CHECK-NEXT: .cfi_def_cfa_offset 16 12; CHECK-NEXT: pushq %rbx 13; CHECK-NEXT: .cfi_def_cfa_offset 24 14; CHECK-NEXT: .cfi_offset %rbx, -24 15; CHECK-NEXT: .cfi_offset %r14, -16 16; CHECK-NEXT: movq %rdx, %r9 17; CHECK-NEXT: movq %rsi, %r8 18; CHECK-NEXT: movq %rsi, %rbx 19; CHECK-NEXT: sarq $63, %rbx 20; CHECK-NEXT: imulq %rdx, %rbx 21; CHECK-NEXT: movq %rdi, %rax 22; CHECK-NEXT: mulq %rdx 23; CHECK-NEXT: movq %rdx, %r10 24; CHECK-NEXT: movq %rax, %rsi 25; CHECK-NEXT: movq %r8, %rax 26; CHECK-NEXT: mulq %r9 27; CHECK-NEXT: movq %rdx, %r9 28; CHECK-NEXT: movq %rax, %r11 29; CHECK-NEXT: addq %r10, %r11 30; CHECK-NEXT: adcq %rbx, %r9 31; CHECK-NEXT: movq %r9, %rbx 32; CHECK-NEXT: sarq $63, %rbx 33; CHECK-NEXT: movq %rcx, %r14 34; CHECK-NEXT: sarq $63, %r14 35; CHECK-NEXT: imulq %rdi, %r14 36; CHECK-NEXT: movq %rdi, %rax 37; CHECK-NEXT: mulq %rcx 38; CHECK-NEXT: movq %rdx, %r10 39; CHECK-NEXT: movq %rax, %rdi 40; CHECK-NEXT: addq %r11, %rdi 41; CHECK-NEXT: adcq %r14, %r10 42; CHECK-NEXT: movq %r10, %r11 43; CHECK-NEXT: sarq $63, %r11 44; CHECK-NEXT: addq %r9, %r10 45; CHECK-NEXT: adcq %rbx, %r11 46; CHECK-NEXT: movq %r8, %rax 47; CHECK-NEXT: imulq %rcx 48; CHECK-NEXT: addq %r10, %rax 49; CHECK-NEXT: adcq %r11, %rdx 50; CHECK-NEXT: movq %rdi, %rcx 51; CHECK-NEXT: sarq $63, %rcx 52; CHECK-NEXT: xorq %rcx, %rdx 53; CHECK-NEXT: xorq %rax, %rcx 54; CHECK-NEXT: orq %rdx, %rcx 55; CHECK-NEXT: jne LBB0_1 56; CHECK-NEXT: ## %bb.2: ## %nooverflow 57; CHECK-NEXT: movq %rsi, %rax 58; CHECK-NEXT: movq %rdi, %rdx 59; CHECK-NEXT: popq %rbx 60; CHECK-NEXT: popq %r14 61; CHECK-NEXT: retq 62; CHECK-NEXT: LBB0_1: ## %overflow 63; CHECK-NEXT: ud2 64entry: 65 %tmp16 = zext i64 %a.coerce0 to i128 66 %tmp11 = zext i64 %a.coerce1 to i128 67 %tmp12 = shl nuw i128 %tmp11, 64 68 %ins14 = or i128 %tmp12, %tmp16 69 %tmp6 = zext i64 %b.coerce0 to i128 70 %tmp3 = zext i64 %b.coerce1 to i128 71 %tmp4 = shl nuw i128 %tmp3, 64 72 %ins = or i128 %tmp4, %tmp6 73 %0 = tail call %1 @llvm.smul.with.overflow.i128(i128 %ins14, i128 %ins) 74 %1 = extractvalue %1 %0, 0 75 %2 = extractvalue %1 %0, 1 76 br i1 %2, label %overflow, label %nooverflow 77 78overflow: ; preds = %entry 79 tail call void @llvm.trap() 80 unreachable 81 82nooverflow: ; preds = %entry 83 %tmp20 = trunc i128 %1 to i64 84 %tmp21 = insertvalue %0 undef, i64 %tmp20, 0 85 %tmp22 = lshr i128 %1, 64 86 %tmp23 = trunc i128 %tmp22 to i64 87 %tmp24 = insertvalue %0 %tmp21, i64 %tmp23, 1 88 ret %0 %tmp24 89} 90 91declare %1 @llvm.smul.with.overflow.i128(i128, i128) nounwind readnone 92 93declare void @llvm.trap() nounwind 94