#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 int int16_t;

/* Variables and functions */
int /*<<< orphan*/ cgc_memcpy(int *, int *, int);
int /*<<< orphan*/ memmove(int *, int *, int);
void convolution(int16_t *samples) {
  static int16_t buf[9 + 80];
  size_t i;
  cgc_memcpy(&buf[9], samples, 80 * sizeof(int16_t));
  for (i = 0; i < 80; i++)
    samples[i] = (buf[i] * buf[i + 9]) >> 16;
  memmove(&buf[0], &buf[80], 9 * sizeof(int16_t));
}


x86 assembly (clang, -O0):
<convolution>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rsi
lea    0x2f09(%rip),%rdi
add    $0x24,%rdi
mov    $0x140,%edx
call   1040 <cgc_memcpy@plt>
movq   $0x0,-0x10(%rbp)
cmpq   $0x50,-0x10(%rbp)
jae    1195 <convolution+0x75>
mov    -0x10(%rbp),%rcx
lea    0x2edd(%rip),%rax
mov    (%rax,%rcx,4),%edx
mov    -0x10(%rbp),%rcx
lea    0x2ecf(%rip),%rax
imul   0x24(%rax,%rcx,4),%edx
sar    $0x10,%edx
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    114d <convolution+0x2d>
lea    0x2ea4(%rip),%rdi
lea    0x2fdd(%rip),%rsi
mov    $0x24,%edx
call   1030 <memmove@plt>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<convolution>:
push   %rbx
mov    %rdi,%rbx
lea    0x2f39(%rip),%rdi
mov    %rbx,%rsi
mov    $0x140,%edx
call   1040 <cgc_memcpy@plt>
lea    0x3065(%rip),%rax
cmp    %rax,%rbx
jae    118d <convolution+0x6d>
lea    0x140(%rbx),%rcx
lea    0x2eee(%rip),%rax
cmp    %rax,%rcx
jbe    118d <convolution+0x6d>
xor    %ecx,%ecx
nopl   0x0(%rax)
mov    0x24(%rax,%rcx,4),%edx
imul   (%rax,%rcx,4),%edx
sar    $0x10,%edx
mov    %edx,(%rbx,%rcx,4)
mov    0x28(%rax,%rcx,4),%edx
imul   0x4(%rax,%rcx,4),%edx
sar    $0x10,%edx
mov    %edx,0x4(%rbx,%rcx,4)
add    $0x2,%rcx
cmp    $0x50,%rcx
jne    1160 <convolution+0x40>
jmp    1216 <convolution+0xf6>
xor    %eax,%eax
lea    0x2eaa(%rip),%rcx
cs nopw 0x0(%rax,%rax,1)
movdqa (%rcx,%rax,4),%xmm0
movdqu 0x24(%rcx,%rax,4),%xmm1
pshufd $0xf5,%xmm1,%xmm2
pmuludq %xmm0,%xmm1
pshufd $0xe8,%xmm1,%xmm1
pshufd $0xf5,%xmm0,%xmm0
pmuludq %xmm0,%xmm2
pshufd $0xe8,%xmm2,%xmm0
punpckldq %xmm0,%xmm1
psrad  $0x10,%xmm1
movdqu %xmm1,(%rbx,%rax,4)
movdqa 0x10(%rcx,%rax,4),%xmm0
movdqu 0x34(%rcx,%rax,4),%xmm1
pshufd $0xf5,%xmm1,%xmm2
pmuludq %xmm0,%xmm1
pshufd $0xe8,%xmm1,%xmm1
pshufd $0xf5,%xmm0,%xmm0
pmuludq %xmm0,%xmm2
pshufd $0xe8,%xmm2,%xmm0
punpckldq %xmm0,%xmm1
psrad  $0x10,%xmm1
movdqu %xmm1,0x10(%rbx,%rax,4)
add    $0x8,%rax
cmp    $0x50,%rax
jne    11a0 <convolution+0x80>
lea    0x2e23(%rip),%rdi
lea    0x2f5c(%rip),%rsi
mov    $0x24,%edx
pop    %rbx
jmp    1030 <memmove@plt>

LLVM IR (-O0):
@convolution.buf = internal global [89 x i32] zeroinitializer
define void @convolution(i32* %0) {
%2 = alloca i32*
%3 = alloca i64
store i32* %0, i32** %2
%4 = load i32*, i32** %2
%5 = call i32 @cgc_memcpy(i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 9), i32* %4, i32 320)
store i64 0, i64* %3
br label %6
6: ; preds = %22, %1
%7 = load i64, i64* %3
%8 = icmp ult i64 %7, 80
br i1 %8, label %9, label %25
9: ; preds = %6
%10 = load i64, i64* %3
%11 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %10
%12 = load i32, i32* %11
%13 = load i64, i64* %3
%14 = add i64 %13, 9
%15 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %14
%16 = load i32, i32* %15
%17 = mul nsw i32 %12, %16
%18 = ashr i32 %17, 16
%19 = load i32*, i32** %2
%20 = load i64, i64* %3
%21 = getelementptr inbounds i32, i32* %19, i64 %20
store i32 %18, i32* %21
br label %22
22: ; preds = %9
%23 = load i64, i64* %3
%24 = add i64 %23, 1
store i64 %24, i64* %3
br label %6
25: ; preds = %6
%26 = call i32 @memmove(i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 0), i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 80), i32 36)
ret void
}

LLVM IR (-O2):
@convolution.buf = internal global [89 x i32] zeroinitializer
define void @convolution(i32* %0) {
%2 = tail call i32 @cgc_memcpy(i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 9), i32* %0, i32 320)
%3 = getelementptr i32, i32* %0, i64 80
%4 = icmp ult i32* %0, getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 1, i64 0)
%5 = icmp ugt i32* %3, getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 0)
%6 = and i1 %4, %5
br i1 %6, label %34, label %7
7: ; preds = %1, %7
%8 = phi i64 [ %32, %7 ], [ 0, %1 ]
%9 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %8
%10 = bitcast i32* %9 to <4 x i32>*
%11 = load <4 x i32>, <4 x i32>* %10
%12 = add nuw nsw i64 %8, 9
%13 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %12
%14 = bitcast i32* %13 to <4 x i32>*
%15 = load <4 x i32>, <4 x i32>* %14
%16 = mul nsw <4 x i32> %15, %11
%17 = ashr <4 x i32> %16, <i32 16, i32 16, i32 16, i32 16>
%18 = getelementptr inbounds i32, i32* %0, i64 %8
%19 = bitcast i32* %18 to <4 x i32>*
store <4 x i32> %17, <4 x i32>* %19
%20 = or i64 %8, 4
%21 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %20
%22 = bitcast i32* %21 to <4 x i32>*
%23 = load <4 x i32>, <4 x i32>* %22
%24 = add nuw nsw i64 %8, 13
%25 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %24
%26 = bitcast i32* %25 to <4 x i32>*
%27 = load <4 x i32>, <4 x i32>* %26
%28 = mul nsw <4 x i32> %27, %23
%29 = ashr <4 x i32> %28, <i32 16, i32 16, i32 16, i32 16>
%30 = getelementptr inbounds i32, i32* %0, i64 %20
%31 = bitcast i32* %30 to <4 x i32>*
store <4 x i32> %29, <4 x i32>* %31
%32 = add nuw nsw i64 %8, 8
%33 = icmp eq i64 %32, 80
br i1 %33, label %55, label %7
34: ; preds = %1, %34
%35 = phi i64 [ %53, %34 ], [ 0, %1 ]
%36 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %35
%37 = load i32, i32* %36
%38 = add nuw nsw i64 %35, 9
%39 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %38
%40 = load i32, i32* %39
%41 = mul nsw i32 %40, %37
%42 = ashr i32 %41, 16
%43 = getelementptr inbounds i32, i32* %0, i64 %35
store i32 %42, i32* %43
%44 = or i64 %35, 1
%45 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %44
%46 = load i32, i32* %45
%47 = add nuw nsw i64 %35, 10
%48 = getelementptr inbounds [89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 %47
%49 = load i32, i32* %48
%50 = mul nsw i32 %49, %46
%51 = ashr i32 %50, 16
%52 = getelementptr inbounds i32, i32* %0, i64 %44
store i32 %51, i32* %52
%53 = add nuw nsw i64 %35, 2
%54 = icmp eq i64 %53, 80
br i1 %54, label %55, label %34
55: ; preds = %7, %34
%56 = tail call i32 @memmove(i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 0), i32* getelementptr inbounds ([89 x i32], [89 x i32]* @convolution.buf, i64 0, i64 80), i32 36)
ret void
}