double eval_poly(x, d, n)
double x, d[];
int n;
{
  int i;
  double res;
  res = d[i = n];
  while (i)
    res = x * res + d[--i];
  return res;
}


x86 assembly (clang, -O0):
<eval_poly>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
mov    %ecx,-0x18(%rbp)
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x20(%rbp)
cmpl   $0x0,-0x18(%rbp)
je     1162 <eval_poly+0x62>
movsd  -0x8(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x18(%rbp)
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1127 <eval_poly+0x27>
movsd  -0x20(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<eval_poly>:
movapd %xmm0,%xmm1
movslq %esi,%rax
movsd  (%rdi,%rax,8),%xmm0
test   %eax,%eax
je     1170 <eval_poly+0x70>
lea    -0x1(%rsi),%ecx
and    $0x3,%esi
je     1133 <eval_poly+0x33>
nopl   0x0(%rax,%rax,1)
mulsd  %xmm1,%xmm0
addsd  -0x8(%rdi,%rax,8),%xmm0
add    $0xffffffffffffffff,%rax
add    $0xffffffff,%esi
jne    1120 <eval_poly+0x20>
cmp    $0x3,%ecx
jb     1170 <eval_poly+0x70>
nopl   0x0(%rax,%rax,1)
mulsd  %xmm1,%xmm0
addsd  -0x8(%rdi,%rax,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  -0x10(%rdi,%rax,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  -0x18(%rdi,%rax,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  -0x20(%rdi,%rax,8),%xmm0
add    $0xfffffffffffffffc,%rax
test   %eax,%eax
jne    1140 <eval_poly+0x40>
ret

LLVM IR (-O0):
define double @eval_poly(double %0, double* %1, i32 %2) {
%4 = alloca double
%5 = alloca double*
%6 = alloca i32
%7 = alloca i32
%8 = alloca double
store double %0, double* %4
store double* %1, double** %5
store i32 %2, i32* %6
%9 = load double*, double** %5
%10 = load i32, i32* %6
store i32 %10, i32* %7
%11 = sext i32 %10 to i64
%12 = getelementptr inbounds double, double* %9, i64 %11
%13 = load double, double* %12
store double %13, double* %8
br label %14
14: ; preds = %17, %3
%15 = load i32, i32* %7
%16 = icmp ne i32 %15, 0
br i1 %16, label %17, label %27
17: ; preds = %14
%18 = load double, double* %4
%19 = load double, double* %8
%20 = load double*, double** %5
%21 = load i32, i32* %7
%22 = add nsw i32 %21, -1
store i32 %22, i32* %7
%23 = sext i32 %22 to i64
%24 = getelementptr inbounds double, double* %20, i64 %23
%25 = load double, double* %24
%26 = call double @llvm.fmuladd.f64(double %18, double %19, double %25)
store double %26, double* %8
br label %14
27: ; preds = %14
%28 = load double, double* %8
ret double %28
}

LLVM IR (-O2):
define double @eval_poly(double %0, double* nocapture %1, i32 %2) {
%4 = sext i32 %2 to i64
%5 = getelementptr inbounds double, double* %1, i64 %4
%6 = load double, double* %5
%7 = icmp eq i32 %2, 0
br i1 %7, label %48, label %8
8: ; preds = %3
%9 = add i32 %2, -1
%10 = and i32 %2, 3
%11 = icmp eq i32 %10, 0
br i1 %11, label %22, label %12
12: ; preds = %8, %12
%13 = phi i64 [ %16, %12 ], [ %4, %8 ]
%14 = phi double [ %19, %12 ], [ %6, %8 ]
%15 = phi i32 [ %20, %12 ], [ 0, %8 ]
%16 = add nsw i64 %13, -1
%17 = getelementptr inbounds double, double* %1, i64 %16
%18 = load double, double* %17
%19 = tail call double @llvm.fmuladd.f64(double %0, double %14, double %18)
%20 = add i32 %15, 1
%21 = icmp eq i32 %20, %10
br i1 %21, label %22, label %12
22: ; preds = %12, %8
%23 = phi double [ undef, %8 ], [ %19, %12 ]
%24 = phi i64 [ %4, %8 ], [ %16, %12 ]
%25 = phi double [ %6, %8 ], [ %19, %12 ]
%26 = icmp ult i32 %9, 3
br i1 %26, label %48, label %27
27: ; preds = %22, %27
%28 = phi i64 [ %42, %27 ], [ %24, %22 ]
%29 = phi double [ %45, %27 ], [ %25, %22 ]
%30 = add nsw i64 %28, -1
%31 = getelementptr inbounds double, double* %1, i64 %30
%32 = load double, double* %31
%33 = tail call double @llvm.fmuladd.f64(double %0, double %29, double %32)
%34 = add nsw i64 %28, -2
%35 = getelementptr inbounds double, double* %1, i64 %34
%36 = load double, double* %35
%37 = tail call double @llvm.fmuladd.f64(double %0, double %33, double %36)
%38 = add nsw i64 %28, -3
%39 = getelementptr inbounds double, double* %1, i64 %38
%40 = load double, double* %39
%41 = tail call double @llvm.fmuladd.f64(double %0, double %37, double %40)
%42 = add nsw i64 %28, -4
%43 = getelementptr inbounds double, double* %1, i64 %42
%44 = load double, double* %43
%45 = tail call double @llvm.fmuladd.f64(double %0, double %41, double %44)
%46 = trunc i64 %42 to i32
%47 = icmp eq i32 %46, 0
br i1 %47, label %48, label %27
48: ; preds = %22, %27, %3
%49 = phi double [ %6, %3 ], [ %23, %22 ], [ %45, %27 ]
ret double %49
}