#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int LDBL_MANT_DIG;
void mul_splitl(long double *hi, long double *lo, long double x,
                long double y) {
  *hi = x * y;
  long double x1 = x * ((1LL << (LDBL_MANT_DIG + 1) / 2) + 1);
  long double y1 = y * ((1LL << (LDBL_MANT_DIG + 1) / 2) + 1);
  x1 = (x - x1) + x1;
  y1 = (y - y1) + y1;
  long double x2 = x - x1;
  long double y2 = y - y1;
  *lo = (((x1 * y1 - *hi) + x1 * y2) + x2 * y1) + x2 * y2;
}


x86 assembly (clang, -O0):
<mul_splitl>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
fldt   0x20(%rbp)
fldt   0x10(%rbp)
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
fstpt  -0x20(%rbp)
fstpt  -0x30(%rbp)
fldt   -0x20(%rbp)
fldt   -0x30(%rbp)
fmulp  %st,%st(1)
mov    -0x8(%rbp),%rax
fstpt  (%rax)
fldt   -0x20(%rbp)
mov    0x2eac(%rip),%rax
mov    %rax,-0x88(%rbp)
mov    (%rax),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %ecx,%eax
shr    $0x1f,%edx
mov    %edx,%ecx
lea    0x1(%rax,%rcx,1),%eax
shr    %eax
mov    %al,%cl
mov    $0x1,%eax
mov    %rax,%rdx
shl    %cl,%rdx
mov    -0x88(%rbp),%rcx
add    $0x1,%rdx
mov    %rdx,-0x80(%rbp)
fildll -0x80(%rbp)
fmulp  %st,%st(1)
fstpt  -0x40(%rbp)
fldt   -0x30(%rbp)
mov    (%rcx),%edx
mov    %edx,%esi
add    $0x1,%esi
mov    %edx,%ecx
shr    $0x1f,%esi
mov    %esi,%edx
lea    0x1(%rcx,%rdx,1),%ecx
shr    %ecx
shl    %cl,%rax
add    $0x1,%rax
mov    %rax,-0x78(%rbp)
fildll -0x78(%rbp)
fmulp  %st,%st(1)
fstpt  -0x50(%rbp)
fldt   -0x20(%rbp)
fldt   -0x40(%rbp)
fsubr  %st,%st(1)
faddp  %st,%st(1)
fstpt  -0x40(%rbp)
fldt   -0x30(%rbp)
fldt   -0x50(%rbp)
fsubr  %st,%st(1)
faddp  %st,%st(1)
fstpt  -0x50(%rbp)
fldt   -0x20(%rbp)
fldt   -0x40(%rbp)
fsubrp %st,%st(1)
fstpt  -0x60(%rbp)
fldt   -0x30(%rbp)
fldt   -0x50(%rbp)
fsubrp %st,%st(1)
fstpt  -0x70(%rbp)
fldt   -0x40(%rbp)
fldt   -0x50(%rbp)
mov    -0x8(%rbp),%rax
fldt   (%rax)
fld    %st(2)
fmul   %st(2),%st
fsubp  %st,%st(1)
fldt   -0x70(%rbp)
fmul   %st,%st(3)
fxch   %st(3)
faddp  %st,%st(1)
fldt   -0x60(%rbp)
fmul   %st,%st(2)
fxch   %st(2)
faddp  %st,%st(1)
fxch   %st(1)
fmulp  %st,%st(2)
faddp  %st,%st(1)
mov    -0x10(%rbp),%rax
fstpt  (%rax)
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<mul_splitl>:
fldt   0x18(%rsp)
fldt   0x8(%rsp)
fld    %st(0)
fmul   %st(2),%st
fld    %st(0)
fstpt  (%rdi)
mov    0x2ec9(%rip),%rax
mov    (%rax),%eax
mov    %eax,%ecx
add    $0x1,%ecx
shr    $0x1f,%ecx
add    %eax,%ecx
add    $0x1,%ecx
shr    %ecx
mov    $0x1,%eax
shl    %cl,%rax
add    $0x1,%rax
mov    %rax,-0x8(%rsp)
fildll -0x8(%rsp)
fld    %st(0)
fmul   %st(3),%st
fxch   %st(1)
fmul   %st(4),%st
fld    %st(3)
fsub   %st(2),%st
faddp  %st,%st(2)
fld    %st(4)
fsub   %st(1),%st
faddp  %st,%st(1)
fxch   %st(3)
fsub   %st(1),%st
fxch   %st(4)
fsub   %st(3),%st
fld    %st(1)
fmul   %st(4),%st
fsubp  %st,%st(3)
fmul   %st,%st(1)
fxch   %st(1)
faddp  %st,%st(2)
fxch   %st(2)
fmul   %st(3),%st
faddp  %st,%st(1)
fxch   %st(2)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  (%rsi)
ret

LLVM IR (-O0):
@LDBL_MANT_DIG = global i32 0
define void @mul_splitl(x86_fp80* %0, x86_fp80* %1, x86_fp80 %2, x86_fp80 %3) {
%5 = alloca x86_fp80*
%6 = alloca x86_fp80*
%7 = alloca x86_fp80
%8 = alloca x86_fp80
%9 = alloca x86_fp80
%10 = alloca x86_fp80
%11 = alloca x86_fp80
%12 = alloca x86_fp80
store x86_fp80* %0, x86_fp80** %5
store x86_fp80* %1, x86_fp80** %6
store x86_fp80 %2, x86_fp80* %7
store x86_fp80 %3, x86_fp80* %8
%13 = load x86_fp80, x86_fp80* %7
%14 = load x86_fp80, x86_fp80* %8
%15 = fmul x86_fp80 %13, %14
%16 = load x86_fp80*, x86_fp80** %5
store x86_fp80 %15, x86_fp80* %16
%17 = load x86_fp80, x86_fp80* %7
%18 = load i32, i32* @LDBL_MANT_DIG
%19 = add nsw i32 %18, 1
%20 = sdiv i32 %19, 2
%21 = zext i32 %20 to i64
%22 = shl i64 1, %21
%23 = add nsw i64 %22, 1
%24 = sitofp i64 %23 to x86_fp80
%25 = fmul x86_fp80 %17, %24
store x86_fp80 %25, x86_fp80* %9
%26 = load x86_fp80, x86_fp80* %8
%27 = load i32, i32* @LDBL_MANT_DIG
%28 = add nsw i32 %27, 1
%29 = sdiv i32 %28, 2
%30 = zext i32 %29 to i64
%31 = shl i64 1, %30
%32 = add nsw i64 %31, 1
%33 = sitofp i64 %32 to x86_fp80
%34 = fmul x86_fp80 %26, %33
store x86_fp80 %34, x86_fp80* %10
%35 = load x86_fp80, x86_fp80* %7
%36 = load x86_fp80, x86_fp80* %9
%37 = fsub x86_fp80 %35, %36
%38 = load x86_fp80, x86_fp80* %9
%39 = fadd x86_fp80 %37, %38
store x86_fp80 %39, x86_fp80* %9
%40 = load x86_fp80, x86_fp80* %8
%41 = load x86_fp80, x86_fp80* %10
%42 = fsub x86_fp80 %40, %41
%43 = load x86_fp80, x86_fp80* %10
%44 = fadd x86_fp80 %42, %43
store x86_fp80 %44, x86_fp80* %10
%45 = load x86_fp80, x86_fp80* %7
%46 = load x86_fp80, x86_fp80* %9
%47 = fsub x86_fp80 %45, %46
store x86_fp80 %47, x86_fp80* %11
%48 = load x86_fp80, x86_fp80* %8
%49 = load x86_fp80, x86_fp80* %10
%50 = fsub x86_fp80 %48, %49
store x86_fp80 %50, x86_fp80* %12
%51 = load x86_fp80, x86_fp80* %9
%52 = load x86_fp80, x86_fp80* %10
%53 = load x86_fp80*, x86_fp80** %5
%54 = load x86_fp80, x86_fp80* %53
%55 = fneg x86_fp80 %54
%56 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %51, x86_fp80 %52, x86_fp80 %55)
%57 = load x86_fp80, x86_fp80* %9
%58 = load x86_fp80, x86_fp80* %12
%59 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %57, x86_fp80 %58, x86_fp80 %56)
%60 = load x86_fp80, x86_fp80* %11
%61 = load x86_fp80, x86_fp80* %10
%62 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %60, x86_fp80 %61, x86_fp80 %59)
%63 = load x86_fp80, x86_fp80* %11
%64 = load x86_fp80, x86_fp80* %12
%65 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %63, x86_fp80 %64, x86_fp80 %62)
%66 = load x86_fp80*, x86_fp80** %6
store x86_fp80 %65, x86_fp80* %66
ret void
}

LLVM IR (-O2):
@LDBL_MANT_DIG = global i32 0
define void @mul_splitl(x86_fp80* nocapture writeonly %0, x86_fp80* nocapture writeonly %1, x86_fp80 %2, x86_fp80 %3) {
%5 = fmul x86_fp80 %2, %3
store x86_fp80 %5, x86_fp80* %0
%6 = load i32, i32* @LDBL_MANT_DIG
%7 = add nsw i32 %6, 1
%8 = sdiv i32 %7, 2
%9 = zext i32 %8 to i64
%10 = shl nuw i64 1, %9
%11 = add nuw nsw i64 %10, 1
%12 = sitofp i64 %11 to x86_fp80
%13 = fmul x86_fp80 %12, %2
%14 = fmul x86_fp80 %12, %3
%15 = fsub x86_fp80 %2, %13
%16 = fadd x86_fp80 %13, %15
%17 = fsub x86_fp80 %3, %14
%18 = fadd x86_fp80 %14, %17
%19 = fsub x86_fp80 %2, %16
%20 = fsub x86_fp80 %3, %18
%21 = fneg x86_fp80 %5
%22 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %16, x86_fp80 %18, x86_fp80 %21)
%23 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %16, x86_fp80 %20, x86_fp80 %22)
%24 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %19, x86_fp80 %18, x86_fp80 %23)
%25 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %19, x86_fp80 %20, x86_fp80 %24)
store x86_fp80 %25, x86_fp80* %1
ret void
}