#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 */
scalar_t__ fabs(double);
double double_sum_err(double a, double b, double *err) {
  double tmp;
  volatile double c, d, e, g, h, f, x;
  if (fabs(a) < fabs(b)) {
    tmp = b;
    b = a;
    a = tmp;
  }
  c = a + b;
  e = c - a;
  g = c - e;
  h = g - a;
  f = b - h;
  d = f - e;
  x = d + e;
  if (x != f) {
    c = a;
    d = b;
  }
  *err = d;
  return c;
}


x86 assembly (clang, -O0):
<double_sum_err>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
movsd  -0x8(%rbp),%xmm0
call   1030 <fabs@plt>
mov    %rax,-0x60(%rbp)
movsd  -0x10(%rbp),%xmm0
call   1030 <fabs@plt>
mov    %rax,%rcx
mov    -0x60(%rbp),%rax
cmp    %rcx,%rax
jge    116c <double_sum_err+0x5c>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x50(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x58(%rbp),%xmm0
movsd  -0x50(%rbp),%xmm1
ucomisd %xmm1,%xmm0
jne    1204 <double_sum_err+0xf4>
jp     1204 <double_sum_err+0xf4>
jmp    1218 <double_sum_err+0x108>
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x28(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<double_sum_err>:
push   %r14
push   %rbx
sub    $0x48,%rsp
mov    %rdi,%r14
movsd  %xmm1,0x8(%rsp)
movsd  %xmm0,0x20(%rsp)
call   1030 <fabs@plt>
mov    %rax,%rbx
movsd  0x8(%rsp),%xmm0
call   1030 <fabs@plt>
cmp    %rax,%rbx
jl     114c <double_sum_err+0x3c>
movsd  0x8(%rsp),%xmm0
movsd  0x20(%rsp),%xmm2
jmp    1158 <double_sum_err+0x48>
movsd  0x20(%rsp),%xmm0
movsd  0x8(%rsp),%xmm2
movapd %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%rsp)
movsd  (%rsp),%xmm1
subsd  %xmm2,%xmm1
movsd  %xmm1,0x10(%rsp)
movsd  (%rsp),%xmm1
subsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x40(%rsp)
movsd  0x40(%rsp),%xmm1
subsd  %xmm2,%xmm1
movsd  %xmm1,0x38(%rsp)
movapd %xmm0,%xmm1
subsd  0x38(%rsp),%xmm1
movsd  %xmm1,0x28(%rsp)
movsd  0x28(%rsp),%xmm1
subsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x18(%rsp)
movsd  0x18(%rsp),%xmm1
addsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x30(%rsp)
movsd  0x30(%rsp),%xmm1
ucomisd 0x28(%rsp),%xmm1
jne    11d9 <double_sum_err+0xc9>
jnp    11e4 <double_sum_err+0xd4>
movsd  %xmm2,(%rsp)
movsd  %xmm0,0x18(%rsp)
movsd  0x18(%rsp),%xmm0
movsd  %xmm0,(%r14)
movsd  (%rsp),%xmm0
add    $0x48,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define double @double_sum_err(double %0, double %1, double* %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double*
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
store double %0, double* %4
store double %1, double* %5
store double* %2, double** %6
%15 = load double, double* %4
%16 = call i64 @fabs(double %15)
%17 = load double, double* %5
%18 = call i64 @fabs(double %17)
%19 = icmp slt i64 %16, %18
br i1 %19, label %20, label %24
20: ; preds = %3
%21 = load double, double* %5
store double %21, double* %7
%22 = load double, double* %4
store double %22, double* %5
%23 = load double, double* %7
store double %23, double* %4
br label %24
24: ; preds = %20, %3
%25 = load double, double* %4
%26 = load double, double* %5
%27 = fadd double %25, %26
store volatile double %27, double* %8
%28 = load volatile double, double* %8
%29 = load double, double* %4
%30 = fsub double %28, %29
store volatile double %30, double* %10
%31 = load volatile double, double* %8
%32 = load volatile double, double* %10
%33 = fsub double %31, %32
store volatile double %33, double* %11
%34 = load volatile double, double* %11
%35 = load double, double* %4
%36 = fsub double %34, %35
store volatile double %36, double* %12
%37 = load double, double* %5
%38 = load volatile double, double* %12
%39 = fsub double %37, %38
store volatile double %39, double* %13
%40 = load volatile double, double* %13
%41 = load volatile double, double* %10
%42 = fsub double %40, %41
store volatile double %42, double* %9
%43 = load volatile double, double* %9
%44 = load volatile double, double* %10
%45 = fadd double %43, %44
store volatile double %45, double* %14
%46 = load volatile double, double* %14
%47 = load volatile double, double* %13
%48 = fcmp une double %46, %47
br i1 %48, label %49, label %52
49: ; preds = %24
%50 = load double, double* %4
store volatile double %50, double* %8
%51 = load double, double* %5
store volatile double %51, double* %9
br label %52
52: ; preds = %49, %24
%53 = load volatile double, double* %9
%54 = load double*, double** %6
store double %53, double* %54
%55 = load volatile double, double* %8
ret double %55
}

LLVM IR (-O2):
define double @double_sum_err(double %0, double %1, double* nocapture writeonly %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = bitcast double* %4 to i8*
%12 = bitcast double* %5 to i8*
%13 = bitcast double* %6 to i8*
%14 = bitcast double* %7 to i8*
%15 = bitcast double* %8 to i8*
%16 = bitcast double* %9 to i8*
%17 = bitcast double* %10 to i8*
%18 = tail call i64 @fabs(double %0)
%19 = tail call i64 @fabs(double %1)
%20 = icmp slt i64 %18, %19
%21 = select i1 %20, double %0, double %1
%22 = select i1 %20, double %1, double %0
%23 = fadd double %22, %21
store volatile double %23, double* %4
%24 = load volatile double, double* %4
%25 = fsub double %24, %22
store volatile double %25, double* %6
%26 = load volatile double, double* %4
%27 = load volatile double, double* %6
%28 = fsub double %26, %27
store volatile double %28, double* %7
%29 = load volatile double, double* %7
%30 = fsub double %29, %22
store volatile double %30, double* %8
%31 = load volatile double, double* %8
%32 = fsub double %21, %31
store volatile double %32, double* %9
%33 = load volatile double, double* %9
%34 = load volatile double, double* %6
%35 = fsub double %33, %34
store volatile double %35, double* %5
%36 = load volatile double, double* %5
%37 = load volatile double, double* %6
%38 = fadd double %36, %37
store volatile double %38, double* %10
%39 = load volatile double, double* %10
%40 = load volatile double, double* %9
%41 = fcmp une double %39, %40
br i1 %41, label %42, label %43
42: ; preds = %3
store volatile double %22, double* %4
store volatile double %21, double* %5
br label %43
43: ; preds = %42, %3
%44 = load volatile double, double* %5
store double %44, double* %2
%45 = load volatile double, double* %4
ret double %45
}