#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 */

/* Variables and functions */
int mul23(int const, int const);
void mod64_a(const int *restrict input, int *restrict output) {
  static const int cos_mod[32] = {
      4195568,   4205700,   4226086,   4256977,   4298755,   4351949,
      4417251,   4495537,   4587901,   4695690,   4820557,   4964534,
      5130115,   5320382,   5539164,   5791261,   -6082752,  -6421430,
      -6817439,  -7284203,  -7839855,  -8509474,  -9328732,  -10350140,
      -11654242, -13371208, -15725922, -19143224, -24533560, -34264200,
      -57015280, -170908480};
  for (int i = 0; i < 16; i++)
    output[i] = mul23(cos_mod[i], input[i] + input[16 + i]);
  for (int i = 16, k = 15; i < 32; i++, k--)
    output[i] = mul23(cos_mod[i], input[k] - input[16 + k]);
}


x86 assembly (clang, -O0):
<mod64_a>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
cmpl   $0x10,-0x14(%rbp)
jge    117a <mod64_a+0x6a>
movslq -0x14(%rbp),%rcx
lea    0xec4(%rip),%rax
mov    (%rax,%rcx,4),%edi
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    (%rax,%rcx,4),%esi
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x10,%ecx
movslq %ecx,%rcx
add    (%rax,%rcx,4),%esi
call   1030 <mul23@plt>
mov    %eax,%edx
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1127 <mod64_a+0x17>
movl   $0x10,-0x18(%rbp)
movl   $0xf,-0x1c(%rbp)
cmpl   $0x20,-0x18(%rbp)
jge    11e4 <mod64_a+0xd4>
movslq -0x18(%rbp),%rcx
lea    0xe63(%rip),%rax
mov    (%rax,%rcx,4),%edi
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    (%rax,%rcx,4),%esi
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x10,%ecx
movslq %ecx,%rcx
sub    (%rax,%rcx,4),%esi
call   1030 <mul23@plt>
mov    %eax,%edx
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
jmp    1188 <mod64_a+0x78>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<mod64_a>:
push   %r15
push   %r14
push   %r12
push   %rbx
push   %rax
mov    %rsi,%r14
mov    %rdi,%r12
xor    %ebx,%ebx
lea    0xed9(%rip),%r15
nopw   0x0(%rax,%rax,1)
mov    (%rbx,%r15,1),%edi
mov    0x40(%r12,%rbx,1),%esi
add    (%r12,%rbx,1),%esi
call   1030 <mul23@plt>
mov    %eax,(%r14,%rbx,1)
add    $0x4,%rbx
cmp    $0x40,%rbx
jne    1130 <mod64_a+0x20>
add    $0x7c,%r12
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
mov    0x40(%r15,%rbx,4),%edi
mov    -0x40(%r12),%esi
sub    (%r12),%esi
call   1030 <mul23@plt>
mov    %eax,0x40(%r14,%rbx,4)
add    $0x1,%rbx
add    $0xfffffffffffffffc,%r12
cmp    $0x10,%rbx
jne    1160 <mod64_a+0x50>
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@mod64_a.cos_mod = internal constant [32 x i32] [i32 4195568, i32 4205700, i32 4226086, i32 4256977, i32 4298755, i32 4351949, i32 4417251, i32 4495537, i32 4587901, i32 4695690, i32 4820557, i32 4964534, i32 5130115, i32 5320382, i32 5539164, i32 5791261, i32 -6082752, i32 -6421430, i32 -6817439, i32 -7284203, i32 -7839855, i32 -8509474, i32 -9328732, i32 -10350140, i32 -11654242, i32 -13371208, i32 -15725922, i32 -19143224, i32 -24533560, i32 -34264200, i32 -57015280, i32 -170908480]
define void @mod64_a(i32* noalias %0, i32* noalias %1) {
%3 = alloca i32*
%4 = alloca i32*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
store i32* %0, i32** %3
store i32* %1, i32** %4
store i32 0, i32* %5
br label %8
8: ; preds = %33, %2
%9 = load i32, i32* %5
%10 = icmp slt i32 %9, 16
br i1 %10, label %11, label %36
11: ; preds = %8
%12 = load i32, i32* %5
%13 = sext i32 %12 to i64
%14 = getelementptr inbounds [32 x i32], [32 x i32]* @mod64_a.cos_mod, i64 0, i64 %13
%15 = load i32, i32* %14
%16 = load i32*, i32** %3
%17 = load i32, i32* %5
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds i32, i32* %16, i64 %18
%20 = load i32, i32* %19
%21 = load i32*, i32** %3
%22 = load i32, i32* %5
%23 = add nsw i32 16, %22
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds i32, i32* %21, i64 %24
%26 = load i32, i32* %25
%27 = add nsw i32 %20, %26
%28 = call i32 @mul23(i32 %15, i32 %27)
%29 = load i32*, i32** %4
%30 = load i32, i32* %5
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds i32, i32* %29, i64 %31
store i32 %28, i32* %32
br label %33
33: ; preds = %11
%34 = load i32, i32* %5
%35 = add nsw i32 %34, 1
store i32 %35, i32* %5
br label %8
36: ; preds = %8
store i32 16, i32* %6
store i32 15, i32* %7
br label %37
37: ; preds = %62, %36
%38 = load i32, i32* %6
%39 = icmp slt i32 %38, 32
br i1 %39, label %40, label %67
40: ; preds = %37
%41 = load i32, i32* %6
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds [32 x i32], [32 x i32]* @mod64_a.cos_mod, i64 0, i64 %42
%44 = load i32, i32* %43
%45 = load i32*, i32** %3
%46 = load i32, i32* %7
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds i32, i32* %45, i64 %47
%49 = load i32, i32* %48
%50 = load i32*, i32** %3
%51 = load i32, i32* %7
%52 = add nsw i32 16, %51
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds i32, i32* %50, i64 %53
%55 = load i32, i32* %54
%56 = sub nsw i32 %49, %55
%57 = call i32 @mul23(i32 %44, i32 %56)
%58 = load i32*, i32** %4
%59 = load i32, i32* %6
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds i32, i32* %58, i64 %60
store i32 %57, i32* %61
br label %62
62: ; preds = %40
%63 = load i32, i32* %6
%64 = add nsw i32 %63, 1
store i32 %64, i32* %6
%65 = load i32, i32* %7
%66 = add nsw i32 %65, -1
store i32 %66, i32* %7
br label %37
67: ; preds = %37
ret void
}

LLVM IR (-O2):
@mod64_a.cos_mod = internal unnamed_addr constant [32 x i32] [i32 4195568, i32 4205700, i32 4226086, i32 4256977, i32 4298755, i32 4351949, i32 4417251, i32 4495537, i32 4587901, i32 4695690, i32 4820557, i32 4964534, i32 5130115, i32 5320382, i32 5539164, i32 5791261, i32 -6082752, i32 -6421430, i32 -6817439, i32 -7284203, i32 -7839855, i32 -8509474, i32 -9328732, i32 -10350140, i32 -11654242, i32 -13371208, i32 -15725922, i32 -19143224, i32 -24533560, i32 -34264200, i32 -57015280, i32 -170908480]
define void @mod64_a(i32* noalias nocapture %0, i32* noalias nocapture writeonly %1) {
br label %3
3: ; preds = %2, %3
%4 = phi i64 [ 0, %2 ], [ %15, %3 ]
%5 = getelementptr inbounds [32 x i32], [32 x i32]* @mod64_a.cos_mod, i64 0, i64 %4
%6 = load i32, i32* %5
%7 = getelementptr inbounds i32, i32* %0, i64 %4
%8 = load i32, i32* %7
%9 = add nuw nsw i64 %4, 16
%10 = getelementptr inbounds i32, i32* %0, i64 %9
%11 = load i32, i32* %10
%12 = add nsw i32 %11, %8
%13 = tail call i32 @mul23(i32 %6, i32 %12)
%14 = getelementptr inbounds i32, i32* %1, i64 %4
store i32 %13, i32* %14
%15 = add nuw nsw i64 %4, 1
%16 = icmp eq i64 %15, 16
br i1 %16, label %18, label %3
17: ; preds = %18
ret void
18: ; preds = %3, %18
%19 = phi i64 [ %31, %18 ], [ 16, %3 ]
%20 = phi i64 [ %32, %18 ], [ 15, %3 ]
%21 = getelementptr inbounds [32 x i32], [32 x i32]* @mod64_a.cos_mod, i64 0, i64 %19
%22 = load i32, i32* %21
%23 = getelementptr inbounds i32, i32* %0, i64 %20
%24 = load i32, i32* %23
%25 = add nuw nsw i64 %20, 16
%26 = getelementptr inbounds i32, i32* %0, i64 %25
%27 = load i32, i32* %26
%28 = sub nsw i32 %24, %27
%29 = tail call i32 @mul23(i32 %22, i32 %28)
%30 = getelementptr inbounds i32, i32* %1, i64 %19
store i32 %29, i32* %30
%31 = add nuw nsw i64 %19, 1
%32 = add nsw i64 %20, -1
%33 = icmp eq i64 %31, 32
br i1 %33, label %17, label %18
}