#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 int32_t;
typedef scalar_t__ int16_t;

/* Variables and functions */
void vec_lmsi16(const int16_t x[], int16_t y[], int n, int16_t error) {
  int i;
  for (i = 0; i < n; i++)
    y[i] += (int16_t)(((int32_t)x[i] * (int32_t)error) >> 15);
}


x86 assembly (clang, -O0):
<vec_lmsi16>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %rcx,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    115d <vec_lmsi16+0x5d>
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x20(%rbp),%rcx
imul   %ecx,%eax
sar    $0xf,%eax
movslq %eax,%rdx
mov    -0x10(%rbp),%rax
movslq -0x24(%rbp),%rcx
add    (%rax,%rcx,8),%rdx
mov    %rdx,(%rax,%rcx,8)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    111a <vec_lmsi16+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<vec_lmsi16>:
test   %edx,%edx
jle    123f <vec_lmsi16+0x13f>
mov    %edx,%r9d
cmp    $0x4,%edx
jb     1122 <vec_lmsi16+0x22>
lea    (%rdi,%r9,8),%rax
cmp    %rsi,%rax
jbe    117e <vec_lmsi16+0x7e>
lea    (%rsi,%r9,8),%rax
cmp    %rdi,%rax
jbe    117e <vec_lmsi16+0x7e>
xor    %edx,%edx
mov    %rdx,%r8
not    %r8
test   $0x1,%r9b
je     1143 <vec_lmsi16+0x43>
mov    (%rdi,%rdx,8),%eax
imul   %ecx,%eax
sar    $0xf,%eax
cltq
add    %rax,(%rsi,%rdx,8)
or     $0x1,%rdx
add    %r9,%r8
je     123f <vec_lmsi16+0x13f>
nopl   0x0(%rax)
mov    (%rdi,%rdx,8),%eax
imul   %ecx,%eax
sar    $0xf,%eax
cltq
add    %rax,(%rsi,%rdx,8)
mov    0x8(%rdi,%rdx,8),%eax
imul   %ecx,%eax
sar    $0xf,%eax
cltq
add    %rax,0x8(%rsi,%rdx,8)
add    $0x2,%rdx
cmp    %rdx,%r9
jne    1150 <vec_lmsi16+0x50>
jmp    123f <vec_lmsi16+0x13f>
mov    %r9d,%edx
and    $0xfffffffc,%edx
movd   %ecx,%xmm0
pshufd $0x50,%xmm0,%xmm0
lea    0x0(,%r9,8),%r8
and    $0xffffffffffffffe0,%r8
xor    %eax,%eax
pshufd $0xf5,%xmm0,%xmm1
movdqu (%rdi,%rax,1),%xmm2
movdqu 0x10(%rdi,%rax,1),%xmm3
movdqa %xmm0,%xmm4
pmuludq %xmm2,%xmm4
pshufd $0xe8,%xmm4,%xmm4
pshufd $0xee,%xmm2,%xmm2
pmuludq %xmm1,%xmm2
pshufd $0xe8,%xmm2,%xmm2
punpckldq %xmm2,%xmm4
movdqa %xmm0,%xmm2
pmuludq %xmm3,%xmm2
pshufd $0xe8,%xmm2,%xmm2
pshufd $0xee,%xmm3,%xmm3
pmuludq %xmm1,%xmm3
pshufd $0xe8,%xmm3,%xmm3
punpckldq %xmm3,%xmm2
psrad  $0xf,%xmm4
psrad  $0xf,%xmm2
pxor   %xmm3,%xmm3
pcmpgtd %xmm4,%xmm3
punpckldq %xmm3,%xmm4
pxor   %xmm3,%xmm3
pcmpgtd %xmm2,%xmm3
punpckldq %xmm3,%xmm2
movdqu (%rsi,%rax,1),%xmm3
paddq  %xmm4,%xmm3
movdqu 0x10(%rsi,%rax,1),%xmm4
paddq  %xmm2,%xmm4
movdqu %xmm3,(%rsi,%rax,1)
movdqu %xmm4,0x10(%rsi,%rax,1)
add    $0x20,%rax
cmp    %rax,%r8
jne    11a0 <vec_lmsi16+0xa0>
cmp    %r9,%rdx
jne    1124 <vec_lmsi16+0x24>
ret

LLVM IR (-O0):
define void @vec_lmsi16(i64* %0, i64* %1, i32 %2, i64 %3) {
%5 = alloca i64*
%6 = alloca i64*
%7 = alloca i32
%8 = alloca i64
%9 = alloca i32
store i64* %0, i64** %5
store i64* %1, i64** %6
store i32 %2, i32* %7
store i64 %3, i64* %8
store i32 0, i32* %9
br label %10
10: ; preds = %32, %4
%11 = load i32, i32* %9
%12 = load i32, i32* %7
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %35
14: ; preds = %10
%15 = load i64*, i64** %5
%16 = load i32, i32* %9
%17 = sext i32 %16 to i64
%18 = getelementptr inbounds i64, i64* %15, i64 %17
%19 = load i64, i64* %18
%20 = trunc i64 %19 to i32
%21 = load i64, i64* %8
%22 = trunc i64 %21 to i32
%23 = mul nsw i32 %20, %22
%24 = ashr i32 %23, 15
%25 = sext i32 %24 to i64
%26 = load i64*, i64** %6
%27 = load i32, i32* %9
%28 = sext i32 %27 to i64
%29 = getelementptr inbounds i64, i64* %26, i64 %28
%30 = load i64, i64* %29
%31 = add nsw i64 %30, %25
store i64 %31, i64* %29
br label %32
32: ; preds = %14
%33 = load i32, i32* %9
%34 = add nsw i32 %33, 1
store i32 %34, i32* %9
br label %10
35: ; preds = %10
ret void
}

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