double interchop(double min, double max, double (*fcn)(double x),
                 double (*chop)(double x)) {
  double f, g, h;
  double x, s, y;
  int i, n;
  n = 65536;
  s = (max - min) / n;
  x = min;
  s = chop(s);
  y = 0;
  for (i = 0; i < n; i++) {
    f = fcn(x);
    g = chop(f);
    x = x + s;
    y = y + g;
    x = chop(x);
    y = chop(y);
  }
  return (y);
}


x86 assembly (clang, -O0):
<interchop>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
mov    %rsi,-0x20(%rbp)
movl   $0x10000,-0x58(%rbp)
movsd  -0x10(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
cvtsi2sdl -0x58(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x20(%rbp),%rax
movsd  -0x48(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x48(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x50(%rbp)
movl   $0x0,-0x54(%rbp)
mov    -0x54(%rbp),%eax
cmp    -0x58(%rbp),%eax
jge    11da <interchop+0xda>
mov    -0x18(%rbp),%rax
movsd  -0x40(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x28(%rbp)
mov    -0x20(%rbp),%rax
movsd  -0x28(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x30(%rbp)
movsd  -0x40(%rbp),%xmm0
addsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x50(%rbp),%xmm0
addsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x20(%rbp),%rax
movsd  -0x40(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x40(%rbp)
mov    -0x20(%rbp),%rax
movsd  -0x50(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x50(%rbp)
mov    -0x54(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x54(%rbp)
jmp    1162 <interchop+0x62>
movsd  -0x50(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<interchop>:
push   %rbp
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rsi,%rbx
mov    %rdi,%r14
movsd  %xmm0,0x10(%rsp)
subsd  %xmm0,%xmm1
mulsd  0xee0(%rip),%xmm1
movapd %xmm1,%xmm0
call   *%rsi
movsd  %xmm0,0x18(%rsp)
xorpd  %xmm0,%xmm0
mov    $0x10000,%ebp
cs nopw 0x0(%rax,%rax,1)
nop
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
call   *%r14
call   *%rbx
movapd %xmm0,%xmm1
movsd  0x10(%rsp),%xmm0
addsd  0x18(%rsp),%xmm0
addsd  0x8(%rsp),%xmm1
movsd  %xmm1,0x8(%rsp)
call   *%rbx
movsd  %xmm0,0x10(%rsp)
movsd  0x8(%rsp),%xmm0
call   *%rbx
add    $0xffffffff,%ebp
jne    1140 <interchop+0x40>
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret

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

LLVM IR (-O2):
define double @interchop(double %0, double %1, double (double)* nocapture %2, double (double)* nocapture %3) {
%5 = fsub double %1, %0
%6 = fmul double %5, 0x3EF0000000000000
%7 = tail call double %3(double %6)
br label %8
8: ; preds = %4, %8
%9 = phi double [ %0, %4 ], [ %16, %8 ]
%10 = phi i32 [ 0, %4 ], [ %18, %8 ]
%11 = phi double [ 0.000000e+00, %4 ], [ %17, %8 ]
%12 = tail call double %2(double %9)
%13 = tail call double %3(double %12)
%14 = fadd double %7, %9
%15 = fadd double %11, %13
%16 = tail call double %3(double %14)
%17 = tail call double %3(double %15)
%18 = add nuw nsw i32 %10, 1
%19 = icmp eq i32 %18, 65536
br i1 %19, label %20, label %8
20: ; preds = %8
ret double %17
}