double findroot(double a, double b, double (*fun)(double)) {
  double m;
  while (b - a > 0.00001) {
    m = (a + b) / 2;
    if ((*fun)(m) > 0)
      b = m;
    else
      a = m;
  }
  return a;
}


x86 assembly (clang, -O0):
<findroot>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  0xed8(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1183 <findroot+0x83>
movsd  -0x8(%rbp),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  0xec4(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x18(%rbp),%rax
movsd  -0x20(%rbp),%xmm0
call   *%rax
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    1174 <findroot+0x74>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    117e <findroot+0x7e>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1116 <findroot+0x16>
movsd  -0x8(%rbp),%xmm0
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<findroot>:
push   %rbx
sub    $0x30,%rsp
movapd %xmm0,%xmm2
movapd %xmm1,%xmm0
subsd  %xmm2,%xmm0
ucomisd 0xee7(%rip),%xmm0
jbe    1199 <findroot+0x99>
mov    %rdi,%rbx
movapd %xmm1,%xmm3
jmp    1159 <findroot+0x59>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
xorpd  %xmm1,%xmm1
cmpltsd %xmm0,%xmm1
andpd  %xmm1,%xmm3
andnpd 0x20(%rsp),%xmm1
orpd   %xmm3,%xmm1
movapd %xmm1,%xmm3
subsd  %xmm2,%xmm1
ucomisd 0xea9(%rip),%xmm1
jbe    1199 <findroot+0x99>
movapd %xmm3,0x20(%rsp)
movsd  %xmm2,0x8(%rsp)
addsd  %xmm2,%xmm3
mulsd  0xe97(%rip),%xmm3
movapd %xmm3,0x10(%rsp)
movapd %xmm3,%xmm0
call   *%rbx
movapd 0x10(%rsp),%xmm3
movsd  0x8(%rsp),%xmm2
ucomisd 0xe7f(%rip),%xmm0
ja     1130 <findroot+0x30>
movapd %xmm3,%xmm2
jmp    1130 <findroot+0x30>
movapd %xmm2,%xmm0
add    $0x30,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define double @findroot(double %0, double %1, double (double)* %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double (double)*
%7 = alloca double
store double %0, double* %4
store double %1, double* %5
store double (double)* %2, double (double)** %6
br label %8
8: ; preds = %26, %3
%9 = load double, double* %5
%10 = load double, double* %4
%11 = fsub double %9, %10
%12 = fcmp ogt double %11, 1.000000e-05
br i1 %12, label %13, label %27
13: ; preds = %8
%14 = load double, double* %4
%15 = load double, double* %5
%16 = fadd double %14, %15
%17 = fdiv double %16, 2.000000e+00
store double %17, double* %7
%18 = load double (double)*, double (double)** %6
%19 = load double, double* %7
%20 = call double %18(double %19)
%21 = fcmp ogt double %20, 0.000000e+00
br i1 %21, label %22, label %24
22: ; preds = %13
%23 = load double, double* %7
store double %23, double* %5
br label %26
24: ; preds = %13
%25 = load double, double* %7
store double %25, double* %4
br label %26
26: ; preds = %24, %22
br label %8
27: ; preds = %8
%28 = load double, double* %4
ret double %28
}

LLVM IR (-O2):
define double @findroot(double %0, double %1, double (double)* nocapture %2) {
%4 = fsub double %1, %0
%5 = fcmp ogt double %4, 1.000000e-05
br i1 %5, label %6, label %17
6: ; preds = %3, %6
%7 = phi double [ %14, %6 ], [ %0, %3 ]
%8 = phi double [ %13, %6 ], [ %1, %3 ]
%9 = fadd double %8, %7
%10 = fmul double %9, 5.000000e-01
%11 = tail call double %2(double %10)
%12 = fcmp ogt double %11, 0.000000e+00
%13 = select i1 %12, double %10, double %8
%14 = select i1 %12, double %7, double %10
%15 = fsub double %13, %14
%16 = fcmp ogt double %15, 1.000000e-05
br i1 %16, label %6, label %17
17: ; preds = %6, %3
%18 = phi double [ %0, %3 ], [ %14, %6 ]
ret double %18
}