double nurbs(unsigned int n, unsigned int p, const double tau[n + 1],
             const double coord[n + 1 - p], const double w[n + 1 - p],
             double x) {
  double sum = 0.;
  double nrm = 0.;
  for (unsigned int i = 0; i < n + 1 - p; i++) {
    double b = bspline(n, i, p, tau, x);
    sum += w[i] * coord[i] * b;
    nrm += w[i] * b;
  }
  return sum / nrm;
}


x86 assembly (clang, -O0):
<nurbs>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %rdx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
movsd  %xmm0,-0x28(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x30(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
movl   $0x0,-0x3c(%rbp)
mov    -0x3c(%rbp),%eax
mov    -0x4(%rbp),%ecx
add    $0x1,%ecx
sub    -0x8(%rbp),%ecx
cmp    %ecx,%eax
jae    11dc <nurbs+0xcc>
mov    -0x4(%rbp),%edi
mov    -0x3c(%rbp),%esi
mov    -0x8(%rbp),%edx
mov    -0x10(%rbp),%rcx
movsd  -0x28(%rbp),%xmm0
mov    $0x1,%al
call   1030 <bspline@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x3c(%rbp),%ecx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x3c(%rbp),%ecx
mulsd  (%rax,%rcx,8),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x30(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x3c(%rbp),%ecx
movsd  (%rax,%rcx,8),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x3c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x3c(%rbp)
jmp    1146 <nurbs+0x36>
movsd  -0x30(%rbp),%xmm0
divsd  -0x38(%rbp),%xmm0
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<nurbs>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    %edi,%eax
sub    %esi,%eax
inc    %eax
je     11b3 <nurbs+0xa3>
mov    %r8,%r15
mov    %rcx,%r12
mov    %rdx,%rbx
mov    %esi,%r13d
mov    %edi,%r14d
mov    %eax,%eax
mov    %rax,(%rsp)
xorpd  %xmm1,%xmm1
xor    %ebp,%ebp
movsd  %xmm0,0x8(%rsp)
nopl   0x0(%rax,%rax,1)
movapd %xmm1,0x10(%rsp)
mov    %r14d,%edi
mov    %ebp,%esi
mov    %r13d,%edx
mov    %rbx,%rcx
movsd  0x8(%rsp),%xmm0
mov    $0x1,%al
call   1030 <bspline@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  (%r15,%rbp,8),%xmm1
movsd  (%r12,%rbp,8),%xmm2
mulsd  %xmm1,%xmm2
unpcklpd %xmm1,%xmm2
movapd 0x10(%rsp),%xmm1
unpcklpd %xmm0,%xmm0
mulpd  %xmm2,%xmm0
addpd  %xmm0,%xmm1
add    $0x1,%rbp
cmp    %rbp,(%rsp)
jne    1150 <nurbs+0x40>
movapd %xmm1,%xmm0
unpckhpd %xmm1,%xmm0
divsd  %xmm0,%xmm1
jmp    11bb <nurbs+0xab>
movsd  0xe45(%rip),%xmm1
movapd %xmm1,%xmm0
add    $0x28,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define double @nurbs(i32 %0, i32 %1, double* %2, double* %3, double* %4, double %5) {
%7 = alloca i32
%8 = alloca i32
%9 = alloca double*
%10 = alloca double*
%11 = alloca double*
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca i32
%16 = alloca double
store i32 %0, i32* %7
store i32 %1, i32* %8
store double* %2, double** %9
store double* %3, double** %10
store double* %4, double** %11
store double %5, double* %12
%17 = load i32, i32* %7
%18 = add i32 %17, 1
%19 = zext i32 %18 to i64
%20 = load i32, i32* %7
%21 = add i32 %20, 1
%22 = load i32, i32* %8
%23 = sub i32 %21, %22
%24 = zext i32 %23 to i64
%25 = load i32, i32* %7
%26 = add i32 %25, 1
%27 = load i32, i32* %8
%28 = sub i32 %26, %27
%29 = zext i32 %28 to i64
store double 0.000000e+00, double* %13
store double 0.000000e+00, double* %14
store i32 0, i32* %15
br label %30
30: ; preds = %67, %6
%31 = load i32, i32* %15
%32 = load i32, i32* %7
%33 = add i32 %32, 1
%34 = load i32, i32* %8
%35 = sub i32 %33, %34
%36 = icmp ult i32 %31, %35
br i1 %36, label %37, label %70
37: ; preds = %30
%38 = load i32, i32* %7
%39 = load i32, i32* %15
%40 = load i32, i32* %8
%41 = load double*, double** %9
%42 = load double, double* %12
%43 = call i32 (i32, i32, i32, double*, double, ...) bitcast (i32 (...)* @bspline to i32 (i32, i32, i32, double*, double, ...)*)(i32 %38, i32 %39, i32 %40, double* %41, double %42)
%44 = sitofp i32 %43 to double
store double %44, double* %16
%45 = load double*, double** %11
%46 = load i32, i32* %15
%47 = zext i32 %46 to i64
%48 = getelementptr inbounds double, double* %45, i64 %47
%49 = load double, double* %48
%50 = load double*, double** %10
%51 = load i32, i32* %15
%52 = zext i32 %51 to i64
%53 = getelementptr inbounds double, double* %50, i64 %52
%54 = load double, double* %53
%55 = fmul double %49, %54
%56 = load double, double* %16
%57 = load double, double* %13
%58 = call double @llvm.fmuladd.f64(double %55, double %56, double %57)
store double %58, double* %13
%59 = load double*, double** %11
%60 = load i32, i32* %15
%61 = zext i32 %60 to i64
%62 = getelementptr inbounds double, double* %59, i64 %61
%63 = load double, double* %62
%64 = load double, double* %16
%65 = load double, double* %14
%66 = call double @llvm.fmuladd.f64(double %63, double %64, double %65)
store double %66, double* %14
br label %67
67: ; preds = %37
%68 = load i32, i32* %15
%69 = add i32 %68, 1
store i32 %69, i32* %15
br label %30
70: ; preds = %30
%71 = load double, double* %13
%72 = load double, double* %14
%73 = fdiv double %71, %72
ret double %73
}

LLVM IR (-O2):
define double @nurbs(i32 %0, i32 %1, double* %2, double* nocapture %3, double* nocapture %4, double %5) {
%7 = add i32 %0, 1
%8 = sub i32 %7, %1
%9 = icmp eq i32 %8, 0
br i1 %9, label %16, label %10
10: ; preds = %6
%11 = zext i32 %8 to i64
br label %18
12: ; preds = %18
%13 = extractelement <2 x double> %33, i64 0
%14 = extractelement <2 x double> %33, i64 1
%15 = fdiv double %13, %14
br label %16
16: ; preds = %12, %6
%17 = phi double [ %15, %12 ], [ 0x7FF8000000000000, %6 ]
ret double %17
18: ; preds = %10, %18
%19 = phi i64 [ 0, %10 ], [ %34, %18 ]
%20 = phi <2 x double> [ zeroinitializer, %10 ], [ %33, %18 ]
%21 = trunc i64 %19 to i32
%22 = tail call i32 (i32, i32, i32, double*, double, ...) bitcast (i32 (...)* @bspline to i32 (i32, i32, i32, double*, double, ...)*)(i32 %0, i32 %21, i32 %1, double* %2, double %5)
%23 = sitofp i32 %22 to double
%24 = getelementptr inbounds double, double* %4, i64 %19
%25 = load double, double* %24
%26 = getelementptr inbounds double, double* %3, i64 %19
%27 = load double, double* %26
%28 = fmul double %25, %27
%29 = insertelement <2 x double> poison, double %28, i64 0
%30 = insertelement <2 x double> %29, double %25, i64 1
%31 = insertelement <2 x double> poison, double %23, i64 0
%32 = shufflevector <2 x double> %31, <2 x double> poison, <2 x i32> zeroinitializer
%33 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %30, <2 x double> %32, <2 x double> %20)
%34 = add nuw nsw i64 %19, 1
%35 = icmp eq i64 %34, %11
br i1 %35, label %12, label %18
}