float fir_filter(float input, float *coef, int n, float *history) {
  int i;
  float *hist_ptr, *hist1_ptr, *coef_ptr;
  float output;
  hist_ptr = history;
  hist1_ptr = hist_ptr;
  coef_ptr = coef + n - 1;
  output = *hist_ptr++ * (*coef_ptr--);
  for (i = 2; i < n; i++) {
    *hist1_ptr++ = *hist_ptr;
    output += (*hist_ptr++) * (*coef_ptr--);
  }
  output += input * (*coef_ptr);
  *hist1_ptr = input;
  return (output);
}


x86 assembly (clang, -O0):
<fir_filter>:
push   %rbp
mov    %rsp,%rbp
movss  %xmm0,-0x4(%rbp)
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
add    $0xfffffffffffffffc,%rax
mov    %rax,-0x40(%rbp)
mov    -0x30(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x30(%rbp)
movss  (%rax),%xmm0
mov    -0x40(%rbp),%rax
mov    %rax,%rcx
add    $0xfffffffffffffffc,%rcx
mov    %rcx,-0x40(%rbp)
mulss  (%rax),%xmm0
movss  %xmm0,-0x44(%rbp)
movl   $0x2,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11da <fir_filter+0xda>
mov    -0x30(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x38(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x38(%rbp)
movss  %xmm0,(%rax)
mov    -0x30(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x30(%rbp)
movss  (%rax),%xmm0
mov    -0x40(%rbp),%rax
mov    %rax,%rcx
add    $0xfffffffffffffffc,%rcx
mov    %rcx,-0x40(%rbp)
movss  (%rax),%xmm2
movss  -0x44(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x44(%rbp)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    116d <fir_filter+0x6d>
movss  -0x4(%rbp),%xmm0
mov    -0x40(%rbp),%rax
movss  (%rax),%xmm2
movss  -0x44(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x44(%rbp)
movss  -0x4(%rbp),%xmm0
mov    -0x38(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x44(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<fir_filter>:
movslq %esi,%rcx
movss  (%rdx),%xmm2
mulss  -0x4(%rdi,%rcx,4),%xmm2
lea    (%rdi,%rcx,4),%rax
add    $0xfffffffffffffff8,%rax
cmp    $0x3,%ecx
jl     11c3 <fir_filter+0xc3>
lea    -0x2(%rsi),%edi
add    $0xfffffffd,%esi
mov    %edi,%ecx
and    $0x3,%ecx
cmp    $0x3,%esi
jb     1197 <fir_filter+0x97>
and    $0xfffffffc,%edi
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movss  0x4(%rdx),%xmm1
movss  0x8(%rdx),%xmm3
movss  %xmm1,(%rdx)
mulss  (%rax),%xmm1
addss  %xmm2,%xmm1
movss  %xmm3,0x4(%rdx)
mulss  -0x4(%rax),%xmm3
addss  %xmm1,%xmm3
movss  0xc(%rdx),%xmm1
movss  %xmm1,0x8(%rdx)
mulss  -0x8(%rax),%xmm1
addss  %xmm3,%xmm1
movss  0x10(%rdx),%xmm2
movss  %xmm2,0xc(%rdx)
mulss  -0xc(%rax),%xmm2
add    $0x10,%rdx
addss  %xmm1,%xmm2
add    $0xfffffffffffffff0,%rax
add    $0xfffffffc,%edi
jne    1140 <fir_filter+0x40>
mov    %rdx,%rsi
test   %ecx,%ecx
je     11c6 <fir_filter+0xc6>
xchg   %ax,%ax
movss  0x4(%rdx),%xmm1
movss  %xmm1,(%rdx)
mulss  (%rax),%xmm1
lea    0x4(%rdx),%rsi
addss  %xmm1,%xmm2
add    $0xfffffffffffffffc,%rax
mov    %rsi,%rdx
add    $0xffffffff,%ecx
jne    11a0 <fir_filter+0xa0>
jmp    11c6 <fir_filter+0xc6>
mov    %rdx,%rsi
movss  (%rax),%xmm1
mulss  %xmm0,%xmm1
addss  %xmm2,%xmm1
movss  %xmm0,(%rsi)
movaps %xmm1,%xmm0
ret

LLVM IR (-O0):
define float @fir_filter(float %0, float* %1, i32 %2, float* %3) {
%5 = alloca float
%6 = alloca float*
%7 = alloca i32
%8 = alloca float*
%9 = alloca i32
%10 = alloca float*
%11 = alloca float*
%12 = alloca float*
%13 = alloca float
store float %0, float* %5
store float* %1, float** %6
store i32 %2, i32* %7
store float* %3, float** %8
%14 = load float*, float** %8
store float* %14, float** %10
%15 = load float*, float** %10
store float* %15, float** %11
%16 = load float*, float** %6
%17 = load i32, i32* %7
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds float, float* %16, i64 %18
%20 = getelementptr inbounds float, float* %19, i64 -1
store float* %20, float** %12
%21 = load float*, float** %10
%22 = getelementptr inbounds float, float* %21, i32 1
store float* %22, float** %10
%23 = load float, float* %21
%24 = load float*, float** %12
%25 = getelementptr inbounds float, float* %24, i32 -1
store float* %25, float** %12
%26 = load float, float* %24
%27 = fmul float %23, %26
store float %27, float* %13
store i32 2, i32* %9
br label %28
28: ; preds = %45, %4
%29 = load i32, i32* %9
%30 = load i32, i32* %7
%31 = icmp slt i32 %29, %30
br i1 %31, label %32, label %48
32: ; preds = %28
%33 = load float*, float** %10
%34 = load float, float* %33
%35 = load float*, float** %11
%36 = getelementptr inbounds float, float* %35, i32 1
store float* %36, float** %11
store float %34, float* %35
%37 = load float*, float** %10
%38 = getelementptr inbounds float, float* %37, i32 1
store float* %38, float** %10
%39 = load float, float* %37
%40 = load float*, float** %12
%41 = getelementptr inbounds float, float* %40, i32 -1
store float* %41, float** %12
%42 = load float, float* %40
%43 = load float, float* %13
%44 = call float @llvm.fmuladd.f32(float %39, float %42, float %43)
store float %44, float* %13
br label %45
45: ; preds = %32
%46 = load i32, i32* %9
%47 = add nsw i32 %46, 1
store i32 %47, i32* %9
br label %28
48: ; preds = %28
%49 = load float, float* %5
%50 = load float*, float** %12
%51 = load float, float* %50
%52 = load float, float* %13
%53 = call float @llvm.fmuladd.f32(float %49, float %51, float %52)
store float %53, float* %13
%54 = load float, float* %5
%55 = load float*, float** %11
store float %54, float* %55
%56 = load float, float* %13
ret float %56
}

LLVM IR (-O2):
define float @fir_filter(float %0, float* nocapture %1, i32 %2, float* nocapture %3) {
%5 = sext i32 %2 to i64
%6 = getelementptr inbounds float, float* %1, i64 %5
%7 = getelementptr inbounds float, float* %6, i64 -1
%8 = load float, float* %3
%9 = load float, float* %7
%10 = fmul float %8, %9
%11 = getelementptr inbounds float, float* %7, i64 -1
%12 = icmp sgt i32 %2, 2
br i1 %12, label %13, label %67
13: ; preds = %4
%14 = add i32 %2, -2
%15 = add i32 %2, -3
%16 = and i32 %14, 3
%17 = icmp ult i32 %15, 3
br i1 %17, label %47, label %18
18: ; preds = %13
%19 = and i32 %14, -4
br label %20
20: ; preds = %20, %18
%21 = phi float* [ %3, %18 ], [ %40, %20 ]
%22 = phi float* [ %11, %18 ], [ %44, %20 ]
%23 = phi float [ %10, %18 ], [ %43, %20 ]
%24 = phi i32 [ 0, %18 ], [ %45, %20 ]
%25 = getelementptr inbounds float, float* %21, i64 1
%26 = load float, float* %25
store float %26, float* %21
%27 = load float, float* %22
%28 = tail call float @llvm.fmuladd.f32(float %26, float %27, float %23)
%29 = getelementptr inbounds float, float* %22, i64 -1
%30 = getelementptr inbounds float, float* %21, i64 2
%31 = load float, float* %30
store float %31, float* %25
%32 = load float, float* %29
%33 = tail call float @llvm.fmuladd.f32(float %31, float %32, float %28)
%34 = getelementptr inbounds float, float* %22, i64 -2
%35 = getelementptr inbounds float, float* %21, i64 3
%36 = load float, float* %35
store float %36, float* %30
%37 = load float, float* %34
%38 = tail call float @llvm.fmuladd.f32(float %36, float %37, float %33)
%39 = getelementptr inbounds float, float* %22, i64 -3
%40 = getelementptr inbounds float, float* %21, i64 4
%41 = load float, float* %40
store float %41, float* %35
%42 = load float, float* %39
%43 = tail call float @llvm.fmuladd.f32(float %41, float %42, float %38)
%44 = getelementptr inbounds float, float* %22, i64 -4
%45 = add i32 %24, 4
%46 = icmp eq i32 %45, %19
br i1 %46, label %47, label %20
47: ; preds = %20, %13
%48 = phi float* [ undef, %13 ], [ %40, %20 ]
%49 = phi float [ undef, %13 ], [ %43, %20 ]
%50 = phi float* [ undef, %13 ], [ %44, %20 ]
%51 = phi float* [ %3, %13 ], [ %40, %20 ]
%52 = phi float* [ %11, %13 ], [ %44, %20 ]
%53 = phi float [ %10, %13 ], [ %43, %20 ]
%54 = icmp eq i32 %16, 0
br i1 %54, label %67, label %55
55: ; preds = %47, %55
%56 = phi float* [ %60, %55 ], [ %51, %47 ]
%57 = phi float* [ %64, %55 ], [ %52, %47 ]
%58 = phi float [ %63, %55 ], [ %53, %47 ]
%59 = phi i32 [ %65, %55 ], [ 0, %47 ]
%60 = getelementptr inbounds float, float* %56, i64 1
%61 = load float, float* %60
store float %61, float* %56
%62 = load float, float* %57
%63 = tail call float @llvm.fmuladd.f32(float %61, float %62, float %58)
%64 = getelementptr inbounds float, float* %57, i64 -1
%65 = add i32 %59, 1
%66 = icmp eq i32 %65, %16
br i1 %66, label %67, label %55
67: ; preds = %47, %55, %4
%68 = phi float* [ %3, %4 ], [ %48, %47 ], [ %60, %55 ]
%69 = phi float [ %10, %4 ], [ %49, %47 ], [ %63, %55 ]
%70 = phi float* [ %11, %4 ], [ %50, %47 ], [ %64, %55 ]
%71 = load float, float* %70
%72 = tail call float @llvm.fmuladd.f32(float %0, float %71, float %69)
store float %0, float* %68
ret float %72
}