int latsynth(short b[], const short k[], long int n, long int f) {
  int i;
  f -= b[n - 1] * k[n - 1];
  for (i = n - 2; i >= 0; i--) {
    f -= b[i] * k[i];
    b[i + 1] = b[i] + ((k[i] * (f >> 16)) >> 16);
  }
  b[0] = f >> 16;
  return f;
}


x86 assembly (clang, -O0):
<latsynth>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%rcx
sub    $0x1,%rcx
movswl (%rax,%rcx,2),%eax
mov    -0x10(%rbp),%rcx
mov    -0x18(%rbp),%rdx
sub    $0x1,%rdx
movswl (%rcx,%rdx,2),%ecx
imul   %ecx,%eax
movslq %eax,%rcx
mov    -0x20(%rbp),%rax
sub    %rcx,%rax
mov    %rax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
sub    $0x2,%rax
mov    %eax,-0x24(%rbp)
cmpl   $0x0,-0x24(%rbp)
jl     11d2 <latsynth+0xd2>
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
movswl (%rax,%rcx,2),%eax
mov    -0x10(%rbp),%rcx
movslq -0x24(%rbp),%rdx
movswl (%rcx,%rdx,2),%ecx
imul   %ecx,%eax
movslq %eax,%rcx
mov    -0x20(%rbp),%rax
sub    %rcx,%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
movswq (%rax,%rcx,2),%rax
mov    -0x10(%rbp),%rcx
movslq -0x24(%rbp),%rdx
movswq (%rcx,%rdx,2),%rcx
mov    -0x20(%rbp),%rdx
sar    $0x10,%rdx
imul   %rdx,%rcx
sar    $0x10,%rcx
add    %rcx,%rax
mov    %ax,%dx
mov    -0x8(%rbp),%rax
mov    -0x24(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dx,(%rax,%rcx,2)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
jmp    1150 <latsynth+0x50>
mov    -0x20(%rbp),%rax
sar    $0x10,%rax
mov    %ax,%cx
mov    -0x8(%rbp),%rax
mov    %cx,(%rax)
mov    -0x20(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<latsynth>:
mov    %rcx,%rax
movswq -0x2(%rdi,%rdx,2),%r8
movswq -0x2(%rsi,%rdx,2),%rcx
imul   %r8,%rcx
sub    %rcx,%rax
add    $0xfffffffe,%edx
js     11c5 <latsynth+0xc5>
mov    %edx,%r9d
test   $0x1,%dl
jne    115a <latsynth+0x5a>
movswq (%rdi,%r9,2),%r8
movswl (%rsi,%r9,2),%ecx
movslq %ecx,%r10
mov    %r8,%rcx
imul   %r10,%rcx
sub    %rcx,%rax
mov    %rax,%rcx
shr    $0x10,%rcx
imul   %ecx,%r10d
shr    $0x10,%r10d
add    %r8d,%r10d
mov    %r10w,0x2(%rdi,%r9,2)
add    $0xffffffffffffffff,%r9
test   %edx,%edx
je     11c5 <latsynth+0xc5>
xchg   %ax,%ax
movswq (%rdi,%r9,2),%r8
movswl (%rsi,%r9,2),%edx
movslq %edx,%rdx
mov    %r8,%rcx
imul   %rdx,%rcx
sub    %rcx,%rax
mov    %rax,%rcx
shr    $0x10,%rcx
imul   %ecx,%edx
shr    $0x10,%edx
add    %r8d,%edx
mov    %dx,0x2(%rdi,%r9,2)
movswq -0x2(%rdi,%r9,2),%r8
movswl -0x2(%rsi,%r9,2),%edx
movslq %edx,%rdx
mov    %r8,%rcx
imul   %rdx,%rcx
sub    %rcx,%rax
mov    %rax,%rcx
shr    $0x10,%rcx
imul   %ecx,%edx
shr    $0x10,%edx
add    %r8d,%edx
mov    %dx,(%rdi,%r9,2)
add    $0xfffffffffffffffe,%r9
cmp    $0xffffffffffffffff,%r9
jne    1160 <latsynth+0x60>
mov    %rax,%rcx
shr    $0x10,%rcx
mov    %cx,(%rdi)
ret

LLVM IR (-O0):
define i32 @latsynth(i16* %0, i16* %1, i64 %2, i64 %3) {
%5 = alloca i16*
%6 = alloca i16*
%7 = alloca i64
%8 = alloca i64
%9 = alloca i32
store i16* %0, i16** %5
store i16* %1, i16** %6
store i64 %2, i64* %7
store i64 %3, i64* %8
%10 = load i16*, i16** %5
%11 = load i64, i64* %7
%12 = sub nsw i64 %11, 1
%13 = getelementptr inbounds i16, i16* %10, i64 %12
%14 = load i16, i16* %13
%15 = sext i16 %14 to i32
%16 = load i16*, i16** %6
%17 = load i64, i64* %7
%18 = sub nsw i64 %17, 1
%19 = getelementptr inbounds i16, i16* %16, i64 %18
%20 = load i16, i16* %19
%21 = sext i16 %20 to i32
%22 = mul nsw i32 %15, %21
%23 = sext i32 %22 to i64
%24 = load i64, i64* %8
%25 = sub nsw i64 %24, %23
store i64 %25, i64* %8
%26 = load i64, i64* %7
%27 = sub nsw i64 %26, 2
%28 = trunc i64 %27 to i32
store i32 %28, i32* %9
br label %29
29: ; preds = %72, %4
%30 = load i32, i32* %9
%31 = icmp sge i32 %30, 0
br i1 %31, label %32, label %75
32: ; preds = %29
%33 = load i16*, i16** %5
%34 = load i32, i32* %9
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds i16, i16* %33, i64 %35
%37 = load i16, i16* %36
%38 = sext i16 %37 to i32
%39 = load i16*, i16** %6
%40 = load i32, i32* %9
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds i16, i16* %39, i64 %41
%43 = load i16, i16* %42
%44 = sext i16 %43 to i32
%45 = mul nsw i32 %38, %44
%46 = sext i32 %45 to i64
%47 = load i64, i64* %8
%48 = sub nsw i64 %47, %46
store i64 %48, i64* %8
%49 = load i16*, i16** %5
%50 = load i32, i32* %9
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds i16, i16* %49, i64 %51
%53 = load i16, i16* %52
%54 = sext i16 %53 to i64
%55 = load i16*, i16** %6
%56 = load i32, i32* %9
%57 = sext i32 %56 to i64
%58 = getelementptr inbounds i16, i16* %55, i64 %57
%59 = load i16, i16* %58
%60 = sext i16 %59 to i64
%61 = load i64, i64* %8
%62 = ashr i64 %61, 16
%63 = mul nsw i64 %60, %62
%64 = ashr i64 %63, 16
%65 = add nsw i64 %54, %64
%66 = trunc i64 %65 to i16
%67 = load i16*, i16** %5
%68 = load i32, i32* %9
%69 = add nsw i32 %68, 1
%70 = sext i32 %69 to i64
%71 = getelementptr inbounds i16, i16* %67, i64 %70
store i16 %66, i16* %71
br label %72
72: ; preds = %32
%73 = load i32, i32* %9
%74 = add nsw i32 %73, -1
store i32 %74, i32* %9
br label %29
75: ; preds = %29
%76 = load i64, i64* %8
%77 = ashr i64 %76, 16
%78 = trunc i64 %77 to i16
%79 = load i16*, i16** %5
%80 = getelementptr inbounds i16, i16* %79, i64 0
store i16 %78, i16* %80
%81 = load i64, i64* %8
%82 = trunc i64 %81 to i32
ret i32 %82
}

LLVM IR (-O2):
define i32 @latsynth(i16* nocapture %0, i16* nocapture %1, i64 %2, i64 %3) {
%5 = add nsw i64 %2, -1
%6 = getelementptr inbounds i16, i16* %0, i64 %5
%7 = load i16, i16* %6
%8 = sext i16 %7 to i64
%9 = getelementptr inbounds i16, i16* %1, i64 %5
%10 = load i16, i16* %9
%11 = sext i16 %10 to i64
%12 = mul nsw i64 %11, %8
%13 = sub nsw i64 %3, %12
%14 = trunc i64 %2 to i32
%15 = add i32 %14, -2
%16 = icmp sgt i32 %15, -1
br i1 %16, label %17, label %78
17: ; preds = %4
%18 = zext i32 %15 to i64
%19 = and i64 %18, 1
%20 = icmp eq i64 %19, 0
br i1 %20, label %21, label %38
21: ; preds = %17
%22 = getelementptr inbounds i16, i16* %0, i64 %18
%23 = load i16, i16* %22
%24 = sext i16 %23 to i64
%25 = getelementptr inbounds i16, i16* %1, i64 %18
%26 = load i16, i16* %25
%27 = sext i16 %26 to i64
%28 = mul nsw i64 %27, %24
%29 = sub nsw i64 %13, %28
%30 = ashr i64 %29, 16
%31 = mul nsw i64 %30, %27
%32 = lshr i64 %31, 16
%33 = trunc i64 %32 to i16
%34 = add i16 %23, %33
%35 = add nuw nsw i64 %18, 1
%36 = getelementptr inbounds i16, i16* %0, i64 %35
store i16 %34, i16* %36
%37 = add nsw i64 %18, -1
br label %38
38: ; preds = %21, %17
%39 = phi i64 [ undef, %17 ], [ %29, %21 ]
%40 = phi i64 [ %18, %17 ], [ %37, %21 ]
%41 = phi i64 [ %13, %17 ], [ %29, %21 ]
%42 = icmp eq i32 %15, 0
br i1 %42, label %78, label %43
43: ; preds = %38, %43
%44 = phi i64 [ %76, %43 ], [ %40, %38 ]
%45 = phi i64 [ %69, %43 ], [ %41, %38 ]
%46 = getelementptr inbounds i16, i16* %0, i64 %44
%47 = load i16, i16* %46
%48 = sext i16 %47 to i64
%49 = getelementptr inbounds i16, i16* %1, i64 %44
%50 = load i16, i16* %49
%51 = sext i16 %50 to i64
%52 = mul nsw i64 %51, %48
%53 = sub nsw i64 %45, %52
%54 = ashr i64 %53, 16
%55 = mul nsw i64 %54, %51
%56 = lshr i64 %55, 16
%57 = trunc i64 %56 to i16
%58 = add i16 %47, %57
%59 = add nuw nsw i64 %44, 1
%60 = getelementptr inbounds i16, i16* %0, i64 %59
store i16 %58, i16* %60
%61 = add nsw i64 %44, -1
%62 = getelementptr inbounds i16, i16* %0, i64 %61
%63 = load i16, i16* %62
%64 = sext i16 %63 to i64
%65 = getelementptr inbounds i16, i16* %1, i64 %61
%66 = load i16, i16* %65
%67 = sext i16 %66 to i64
%68 = mul nsw i64 %67, %64
%69 = sub nsw i64 %53, %68
%70 = ashr i64 %69, 16
%71 = mul nsw i64 %70, %67
%72 = lshr i64 %71, 16
%73 = trunc i64 %72 to i16
%74 = add i16 %63, %73
%75 = getelementptr inbounds i16, i16* %0, i64 %44
store i16 %74, i16* %75
%76 = add nsw i64 %44, -2
%77 = icmp eq i64 %61, 0
br i1 %77, label %78, label %43
78: ; preds = %38, %43, %4
%79 = phi i64 [ %13, %4 ], [ %39, %38 ], [ %69, %43 ]
%80 = lshr i64 %79, 16
%81 = trunc i64 %80 to i16
store i16 %81, i16* %0
%82 = trunc i64 %79 to i32
ret i32 %82
}