void foo(int *data, unsigned len, const int qlp_coeff[], int lp,
         int residual[]) {
  int i;
  int sum;
  for (i = 0; i < (int)len; i++) {
    sum = 0;
    sum += qlp_coeff[1] * data[i - 2];
    sum += qlp_coeff[0] * data[i - 1];
    residual[i] = data[i] - (sum >> lp);
  }
}


x86 assembly (clang, -O0):
<foo>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    %r8,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    1199 <foo+0x99>
movl   $0x0,-0x30(%rbp)
mov    -0x18(%rbp),%rax
mov    0x4(%rax),%eax
mov    -0x8(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x2,%edx
movslq %edx,%rdx
imul   (%rcx,%rdx,4),%eax
add    -0x30(%rbp),%eax
mov    %eax,-0x30(%rbp)
mov    -0x18(%rbp),%rax
mov    (%rax),%eax
mov    -0x8(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
imul   (%rcx,%rdx,4),%eax
add    -0x30(%rbp),%eax
mov    %eax,-0x30(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,4),%edx
mov    -0x30(%rbp),%eax
mov    -0x1c(%rbp),%ecx
sar    %cl,%eax
sub    %eax,%edx
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    111d <foo+0x1d>
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %rbx
test   %esi,%esi
jle    1235 <foo+0x135>
mov    %esi,%r10d
cmp    $0x4,%esi
jae    1118 <foo+0x18>
xor    %esi,%esi
jmp    1210 <foo+0x110>
lea    (%r8,%r10,4),%rsi
lea    0x8(%rdx),%rax
cmp    %r8,%rax
seta   %r11b
lea    -0x8(%rdi),%r9
cmp    %rdx,%rsi
seta   %bl
lea    (%rdi,%r10,4),%rax
cmp    %r8,%rax
seta   %al
cmp    %rsi,%r9
setb   %r9b
xor    %esi,%esi
test   %bl,%r11b
jne    1210 <foo+0x110>
and    %r9b,%al
jne    1210 <foo+0x110>
mov    %r10d,%esi
and    $0xfffffffc,%esi
movd   %ecx,%xmm5
movd   0x4(%rdx),%xmm0
pshufd $0x0,%xmm0,%xmm8
movd   (%rdx),%xmm1
pshufd $0x0,%xmm1,%xmm1
lea    0x0(,%r10,4),%r9
and    $0xfffffffffffffff0,%r9
xor    %eax,%eax
pshufd $0xf5,%xmm8,%xmm2
pshufd $0xf5,%xmm1,%xmm3
xorps  %xmm4,%xmm4
movss  %xmm5,%xmm4
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movdqu -0x8(%rdi,%rax,1),%xmm5
movdqu -0x4(%rdi,%rax,1),%xmm6
movdqu (%rdi,%rax,1),%xmm7
pshufd $0xf5,%xmm5,%xmm0
pmuludq %xmm8,%xmm5
pshufd $0xe8,%xmm5,%xmm5
pmuludq %xmm2,%xmm0
pshufd $0xe8,%xmm0,%xmm0
punpckldq %xmm0,%xmm5
pshufd $0xf5,%xmm6,%xmm0
pmuludq %xmm1,%xmm6
pshufd $0xe8,%xmm6,%xmm6
pmuludq %xmm3,%xmm0
pshufd $0xe8,%xmm0,%xmm0
punpckldq %xmm0,%xmm6
paddd  %xmm5,%xmm6
psrad  %xmm4,%xmm6
psubd  %xmm6,%xmm7
movdqu %xmm7,(%r8,%rax,1)
add    $0x10,%rax
cmp    %rax,%r9
jne    11a0 <foo+0xa0>
cmp    %r10,%rsi
je     1235 <foo+0x135>
nopl   0x0(%rax,%rax,1)
mov    -0x8(%rdi,%rsi,4),%eax
imul   0x4(%rdx),%eax
mov    -0x4(%rdi,%rsi,4),%ebx
imul   (%rdx),%ebx
add    %eax,%ebx
mov    (%rdi,%rsi,4),%eax
sar    %cl,%ebx
sub    %ebx,%eax
mov    %eax,(%r8,%rsi,4)
add    $0x1,%rsi
cmp    %rsi,%r10
jne    1210 <foo+0x110>
pop    %rbx
ret

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

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