#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef size_t uint32_t;

/* Variables and functions */
float filter_run_fir_iteration(float *vector, float *filter, int bits,
                               uint32_t offset) {
  float result = 0;
  int size = 1 << bits;
  uint32_t cnt_mask = 0xFFFFFFFF >> (32 - bits);
  for (int i = 0; i < size; i++) {
    result += filter[i] * vector[offset];
    offset++;
    offset &= cnt_mask;
  }
  return result;
}


x86 assembly (clang, -O0):
<filter_run_fir_iteration>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %rcx,-0x20(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x24(%rbp)
mov    -0x14(%rbp),%ecx
mov    $0x1,%eax
shl    %cl,%eax
mov    %eax,-0x28(%rbp)
mov    $0x20,%ecx
sub    -0x14(%rbp),%ecx
mov    $0xffffffff,%eax
shr    %cl,%eax
mov    %eax,%eax
mov    %rax,-0x30(%rbp)
movl   $0x0,-0x34(%rbp)
mov    -0x34(%rbp),%eax
cmp    -0x28(%rbp),%eax
jge    11a2 <filter_run_fir_iteration+0xa2>
mov    -0x10(%rbp),%rax
movslq -0x34(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm2
movss  -0x24(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x24(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x30(%rbp),%rax
and    -0x20(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    1144 <filter_run_fir_iteration+0x44>
movss  -0x24(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<filter_run_fir_iteration>:
mov    %rcx,%rax
mov    %edx,%ecx
neg    %cl
mov    $0xffffffff,%r9d
shr    %cl,%r9d
xorps  %xmm0,%xmm0
cmp    $0x1f,%edx
je     119c <filter_run_fir_iteration+0x9c>
mov    $0x1,%r8d
mov    %edx,%ecx
shl    %cl,%r8d
mov    $0x1,%ecx
cmp    $0x2,%r8d
cmovl  %ecx,%r8d
jge    113d <filter_run_fir_iteration+0x3d>
xor    %ecx,%ecx
xorps  %xmm0,%xmm0
jmp    1185 <filter_run_fir_iteration+0x85>
mov    %r8d,%edx
and    $0x7ffffffe,%edx
xorps  %xmm1,%xmm1
xor    %ecx,%ecx
nopl   0x0(%rax,%rax,1)
movss  (%rsi,%rcx,4),%xmm2
movss  0x4(%rsi,%rcx,4),%xmm0
mulss  (%rdi,%rax,4),%xmm2
addss  %xmm1,%xmm2
add    $0x1,%eax
and    %r9d,%eax
mulss  (%rdi,%rax,4),%xmm0
addss  %xmm2,%xmm0
add    $0x1,%eax
and    %r9d,%eax
add    $0x2,%rcx
movaps %xmm0,%xmm1
cmp    %rcx,%rdx
jne    1150 <filter_run_fir_iteration+0x50>
test   $0x1,%r8b
je     119c <filter_run_fir_iteration+0x9c>
movss  (%rsi,%rcx,4),%xmm1
mulss  (%rdi,%rax,4),%xmm1
addss  %xmm0,%xmm1
movaps %xmm1,%xmm0
ret

LLVM IR (-O0):
define float @filter_run_fir_iteration(float* %0, float* %1, i32 %2, i64 %3) {
%5 = alloca float*
%6 = alloca float*
%7 = alloca i32
%8 = alloca i64
%9 = alloca float
%10 = alloca i32
%11 = alloca i64
%12 = alloca i32
store float* %0, float** %5
store float* %1, float** %6
store i32 %2, i32* %7
store i64 %3, i64* %8
store float 0.000000e+00, float* %9
%13 = load i32, i32* %7
%14 = shl i32 1, %13
store i32 %14, i32* %10
%15 = load i32, i32* %7
%16 = sub nsw i32 32, %15
%17 = lshr i32 -1, %16
%18 = zext i32 %17 to i64
store i64 %18, i64* %11
store i32 0, i32* %12
br label %19
19: ; preds = %40, %4
%20 = load i32, i32* %12
%21 = load i32, i32* %10
%22 = icmp slt i32 %20, %21
br i1 %22, label %23, label %43
23: ; preds = %19
%24 = load float*, float** %6
%25 = load i32, i32* %12
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds float, float* %24, i64 %26
%28 = load float, float* %27
%29 = load float*, float** %5
%30 = load i64, i64* %8
%31 = getelementptr inbounds float, float* %29, i64 %30
%32 = load float, float* %31
%33 = load float, float* %9
%34 = call float @llvm.fmuladd.f32(float %28, float %32, float %33)
store float %34, float* %9
%35 = load i64, i64* %8
%36 = add i64 %35, 1
store i64 %36, i64* %8
%37 = load i64, i64* %11
%38 = load i64, i64* %8
%39 = and i64 %38, %37
store i64 %39, i64* %8
br label %40
40: ; preds = %23
%41 = load i32, i32* %12
%42 = add nsw i32 %41, 1
store i32 %42, i32* %12
br label %19
43: ; preds = %19
%44 = load float, float* %9
ret float %44
}

LLVM IR (-O2):
define float @filter_run_fir_iteration(float* nocapture %0, float* nocapture %1, i32 %2, i64 %3) {
%5 = sub nsw i32 32, %2
%6 = lshr i32 -1, %5
%7 = zext i32 %6 to i64
%8 = icmp eq i32 %2, 31
br i1 %8, label %29, label %9
9: ; preds = %4
%10 = shl nuw nsw i32 1, %2
%11 = call i32 @llvm.smax.i32(i32 %10, i32 1)
%12 = zext i32 %11 to i64
%13 = and i64 %12, 1
%14 = icmp slt i32 %10, 2
br i1 %14, label %17, label %15
15: ; preds = %9
%16 = and i64 %12, 2147483646
br label %31
17: ; preds = %31, %9
%18 = phi float [ undef, %9 ], [ %48, %31 ]
%19 = phi i64 [ 0, %9 ], [ %51, %31 ]
%20 = phi i64 [ %3, %9 ], [ %50, %31 ]
%21 = phi float [ 0.000000e+00, %9 ], [ %48, %31 ]
%22 = icmp eq i64 %13, 0
br i1 %22, label %29, label %23
23: ; preds = %17
%24 = getelementptr inbounds float, float* %1, i64 %19
%25 = load float, float* %24
%26 = getelementptr inbounds float, float* %0, i64 %20
%27 = load float, float* %26
%28 = tail call float @llvm.fmuladd.f32(float %25, float %27, float %21)
br label %29
29: ; preds = %23, %17, %4
%30 = phi float [ 0.000000e+00, %4 ], [ %18, %17 ], [ %28, %23 ]
ret float %30
31: ; preds = %31, %15
%32 = phi i64 [ 0, %15 ], [ %51, %31 ]
%33 = phi i64 [ %3, %15 ], [ %50, %31 ]
%34 = phi float [ 0.000000e+00, %15 ], [ %48, %31 ]
%35 = phi i64 [ 0, %15 ], [ %52, %31 ]
%36 = getelementptr inbounds float, float* %1, i64 %32
%37 = load float, float* %36
%38 = getelementptr inbounds float, float* %0, i64 %33
%39 = load float, float* %38
%40 = tail call float @llvm.fmuladd.f32(float %37, float %39, float %34)
%41 = add i64 %33, 1
%42 = and i64 %41, %7
%43 = or i64 %32, 1
%44 = getelementptr inbounds float, float* %1, i64 %43
%45 = load float, float* %44
%46 = getelementptr inbounds float, float* %0, i64 %42
%47 = load float, float* %46
%48 = tail call float @llvm.fmuladd.f32(float %45, float %47, float %40)
%49 = add nuw nsw i64 %42, 1
%50 = and i64 %49, %7
%51 = add nuw nsw i64 %32, 2
%52 = add i64 %35, 2
%53 = icmp eq i64 %52, %16
br i1 %53, label %17, label %31
}