long double trapezoid(long double (*f)(long double), long double a,
                      long double b, int n) {
  long double sum = (0.5) * (f(a) + f(b));
  long double h = (b - a) / n;
  for (int i = 1; i < n; i++) {
    long double x = a + (i * h);
    sum += f(x);
  }
  return sum * h;
}


x86 assembly (clang, -O0):
<trapezoid>:
push   %rbp
mov    %rsp,%rbp
sub    $0xb0,%rsp
fldt   0x20(%rbp)
fldt   0x10(%rbp)
mov    %rdi,-0x8(%rbp)
fstpt  -0x20(%rbp)
fstpt  -0x30(%rbp)
mov    %esi,-0x34(%rbp)
mov    -0x8(%rbp),%rax
fldt   -0x20(%rbp)
mov    %rsp,%rcx
fstpt  (%rcx)
call   *%rax
fstpt  -0x94(%rbp)
mov    -0x8(%rbp),%rax
fldt   -0x30(%rbp)
mov    %rsp,%rcx
fstpt  (%rcx)
call   *%rax
fldt   -0x94(%rbp)
faddp  %st,%st(1)
flds   0xeb2(%rip)
fmulp  %st,%st(1)
fstpt  -0x50(%rbp)
fldt   -0x30(%rbp)
fldt   -0x20(%rbp)
fsubrp %st,%st(1)
mov    -0x34(%rbp),%eax
mov    %eax,-0x84(%rbp)
fildl  -0x84(%rbp)
fdivrp %st,%st(1)
fstpt  -0x60(%rbp)
movl   $0x1,-0x64(%rbp)
mov    -0x64(%rbp),%eax
cmp    -0x34(%rbp),%eax
jge    11c2 <trapezoid+0xc2>
fldt   -0x20(%rbp)
mov    -0x64(%rbp),%eax
mov    %eax,-0x88(%rbp)
fildl  -0x88(%rbp)
fldt   -0x60(%rbp)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  -0x80(%rbp)
mov    -0x8(%rbp),%rax
fldt   -0x80(%rbp)
mov    %rsp,%rcx
fstpt  (%rcx)
call   *%rax
fldt   -0x50(%rbp)
faddp  %st,%st(1)
fstpt  -0x50(%rbp)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1176 <trapezoid+0x76>
fldt   -0x50(%rbp)
fldt   -0x60(%rbp)
fmulp  %st,%st(1)
add    $0xb0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<trapezoid>:
push   %r14
push   %rbx
sub    $0x58,%rsp
mov    %esi,%ebx
mov    %rdi,%r14
fldt   0x70(%rsp)
fld    %st(0)
fstpt  0x34(%rsp)
fldt   0x80(%rsp)
fstpt  0x18(%rsp)
fstpt  (%rsp)
call   *%rdi
fstpt  0x24(%rsp)
fldt   0x18(%rsp)
fstpt  (%rsp)
call   *%r14
fldt   0x34(%rsp)
fldt   0x24(%rsp)
faddp  %st,%st(2)
fxch   %st(1)
fmuls  0xeba(%rip)
fldt   0x18(%rsp)
fsub   %st(2),%st
mov    %ebx,0x30(%rsp)
fidivl 0x30(%rsp)
cmp    $0x2,%ebx
jl     11bd <trapezoid+0xbd>
add    $0xffffffff,%ebx
fld1
fld    %st(0)
fstpt  0x40(%rsp)
fxch   %st(1)
fstpt  0x24(%rsp)
fldz
nopl   0x0(%rax)
fstp   %st(0)
fld    %st(0)
fstpt  0x18(%rsp)
fxch   %st(1)
fstpt  0x4c(%rsp)
fldt   0x24(%rsp)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  (%rsp)
call   *%r14
fldt   0x4c(%rsp)
fldt   0x34(%rsp)
fxch   %st(1)
faddp  %st,%st(2)
fldt   0x24(%rsp)
fldt   0x40(%rsp)
fldt   0x18(%rsp)
faddp  %st,%st(1)
fstpt  0x18(%rsp)
fldt   0x18(%rsp)
add    $0xffffffff,%ebx
fxch   %st(2)
fxch   %st(3)
fxch   %st(2)
fxch   %st(1)
jne    1170 <trapezoid+0x70>
jmp    11c7 <trapezoid+0xc7>
fstp   %st(2)
fldz
fldz
fxch   %st(1)
fxch   %st(3)
fstp   %st(3)
fstp   %st(0)
fmulp  %st,%st(1)
add    $0x58,%rsp
pop    %rbx
pop    %r14
ret

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

LLVM IR (-O2):
define x86_fp80 @trapezoid(x86_fp80 (x86_fp80)* nocapture %0, x86_fp80 %1, x86_fp80 %2, i32 %3) {
%5 = tail call x86_fp80 %0(x86_fp80 %1)
%6 = tail call x86_fp80 %0(x86_fp80 %2)
%7 = fadd x86_fp80 %5, %6
%8 = fmul x86_fp80 %7, 0xK3FFE8000000000000000
%9 = fsub x86_fp80 %2, %1
%10 = sitofp i32 %3 to x86_fp80
%11 = fdiv x86_fp80 %9, %10
%12 = icmp sgt i32 %3, 1
br i1 %12, label %16, label %13
13: ; preds = %16, %4
%14 = phi x86_fp80 [ %8, %4 ], [ %22, %16 ]
%15 = fmul x86_fp80 %11, %14
ret x86_fp80 %15
16: ; preds = %4, %16
%17 = phi x86_fp80 [ %22, %16 ], [ %8, %4 ]
%18 = phi i32 [ %23, %16 ], [ 1, %4 ]
%19 = sitofp i32 %18 to x86_fp80
%20 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %19, x86_fp80 %11, x86_fp80 %1)
%21 = tail call x86_fp80 %0(x86_fp80 %20)
%22 = fadd x86_fp80 %17, %21
%23 = add nuw nsw i32 %18, 1
%24 = icmp eq i32 %23, %3
br i1 %24, label %13, label %16
}