double EvalPoly(double *P, int n, double x) {
  double tmp = P[n];
  while (n--) {
    tmp = tmp * x + P[n];
  }
  return tmp;
}


x86 assembly (clang, -O0):
<EvalPoly>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0xc(%rbp)
cmp    $0x0,%eax
je     115f <EvalPoly+0x5f>
movsd  -0x20(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm2
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1122 <EvalPoly+0x22>
movsd  -0x20(%rbp),%xmm0
pop    %rbp
ret

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

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

LLVM IR (-O2):
define double @EvalPoly(double* nocapture %0, i32 %1, double %2) {
%4 = sext i32 %1 to i64
%5 = getelementptr inbounds double, double* %0, i64 %4
%6 = load double, double* %5
%7 = icmp eq i32 %1, 0
br i1 %7, label %48, label %8
8: ; preds = %3
%9 = add i32 %1, -1
%10 = and i32 %1, 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* %0, i64 %16
%18 = load double, double* %17
%19 = tail call double @llvm.fmuladd.f64(double %14, double %2, 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* %0, i64 %30
%32 = load double, double* %31
%33 = tail call double @llvm.fmuladd.f64(double %29, double %2, double %32)
%34 = add nsw i64 %28, -2
%35 = getelementptr inbounds double, double* %0, i64 %34
%36 = load double, double* %35
%37 = tail call double @llvm.fmuladd.f64(double %33, double %2, double %36)
%38 = add nsw i64 %28, -3
%39 = getelementptr inbounds double, double* %0, i64 %38
%40 = load double, double* %39
%41 = tail call double @llvm.fmuladd.f64(double %37, double %2, double %40)
%42 = add nsw i64 %28, -4
%43 = getelementptr inbounds double, double* %0, i64 %42
%44 = load double, double* %43
%45 = tail call double @llvm.fmuladd.f64(double %41, double %2, 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
}