#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 /*<<< orphan*/ memcpy(unsigned short **, unsigned short **, int);
void eval_ccga(int dimensions, unsigned short (*pop)[dimensions][100],
               int (*curr_best)[dimensions],
               double (*func_ptr)(unsigned short (*pop)[dimensions]),
               double (*fitnesses)[dimensions][100]) {
  unsigned short best[dimensions];
  unsigned short eval_vector[dimensions];
  for (int i = 0; i < dimensions; i++) {
    best[i] = (*pop)[i][(*curr_best)[i]];
  }
  for (int i = 0; i < dimensions; i++) {
    memcpy(&eval_vector, &best, sizeof(unsigned short) * dimensions);
    for (int j = 0; j < 100; j++) {
      eval_vector[i] = (*pop)[i][j];
      (*fitnesses)[i][j] = func_ptr(&eval_vector);
    }
  }
}


x86 assembly (clang, -O0):
<eval_ccga>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    -0x4(%rbp),%eax
mov    %rsp,%rcx
mov    %rcx,-0x30(%rbp)
lea    0xf(%rax,%rax,1),%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rsp,%rcx
sub    %rdx,%rcx
mov    %rcx,-0x60(%rbp)
mov    %rcx,%rsp
mov    %rax,-0x38(%rbp)
mov    -0x4(%rbp),%eax
lea    0xf(%rax,%rax,1),%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rsp,%rcx
sub    %rdx,%rcx
mov    %rcx,-0x58(%rbp)
mov    %rcx,%rsp
mov    %rax,-0x40(%rbp)
movl   $0x0,-0x44(%rbp)
mov    -0x44(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    11bb <eval_ccga+0xab>
mov    -0x60(%rbp),%rax
mov    -0x10(%rbp),%rcx
movslq -0x44(%rbp),%rdx
imul   $0xc8,%rdx,%rdx
add    %rdx,%rcx
mov    -0x18(%rbp),%rdx
movslq -0x44(%rbp),%rsi
movslq (%rdx,%rsi,4),%rdx
mov    (%rcx,%rdx,2),%dx
movslq -0x44(%rbp),%rcx
mov    %dx,(%rax,%rcx,2)
mov    -0x44(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44(%rbp)
jmp    1173 <eval_ccga+0x63>
movl   $0x0,-0x48(%rbp)
mov    -0x48(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    125b <eval_ccga+0x14b>
mov    -0x60(%rbp),%rsi
mov    -0x58(%rbp),%rdi
movslq -0x4(%rbp),%rax
shl    $0x1,%rax
mov    %eax,%edx
call   1030 <memcpy@plt>
movl   $0x0,-0x4c(%rbp)
cmpl   $0x64,-0x4c(%rbp)
jge    1248 <eval_ccga+0x138>
mov    -0x58(%rbp),%rdi
mov    -0x10(%rbp),%rax
movslq -0x48(%rbp),%rcx
imul   $0xc8,%rcx,%rcx
add    %rcx,%rax
movslq -0x4c(%rbp),%rcx
mov    (%rax,%rcx,2),%cx
movslq -0x48(%rbp),%rax
mov    %cx,(%rdi,%rax,2)
call   *-0x20(%rbp)
mov    -0x28(%rbp),%rax
movslq -0x48(%rbp),%rcx
imul   $0x320,%rcx,%rcx
add    %rcx,%rax
movslq -0x4c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x4c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x4c(%rbp)
jmp    11ec <eval_ccga+0xdc>
jmp    124d <eval_ccga+0x13d>
mov    -0x48(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x48(%rbp)
jmp    11c2 <eval_ccga+0xb2>
mov    -0x30(%rbp),%rax
mov    %rax,%rsp
mov    %rbp,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<eval_ccga>:
push   %rbp
mov    %rsp,%rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    %rcx,-0x50(%rbp)
mov    %rsi,%rbx
mov    %edi,%r11d
mov    %rsp,%rsi
lea    (%r11,%r11,1),%rax
add    $0xf,%rax
and    $0xfffffffffffffff0,%rax
sub    %rax,%rsi
mov    %rsi,%rsp
mov    %rsp,%r13
sub    %rax,%r13
mov    %r13,%rsp
mov    %edi,-0x2c(%rbp)
test   %edi,%edi
jle    129b <eval_ccga+0x18b>
mov    %r8,%r12
lea    -0x1(%r11),%rcx
mov    %r11d,%r9d
and    $0x3,%r9d
cmp    $0x3,%rcx
jae    116c <eval_ccga+0x5c>
xor    %ecx,%ecx
jmp    11d2 <eval_ccga+0xc2>
mov    %r11d,%r10d
and    $0xfffffffc,%r10d
lea    0x190(%rbx),%rdi
xor    %ecx,%ecx
nopl   0x0(%rax)
movslq (%rdx,%rcx,4),%rax
movzwl -0x190(%rdi,%rax,2),%eax
ff
mov    %ax,(%rsi,%rcx,2)
movslq 0x4(%rdx,%rcx,4),%rax
movzwl -0xc8(%rdi,%rax,2),%eax
ff
mov    %ax,0x2(%rsi,%rcx,2)
movslq 0x8(%rdx,%rcx,4),%rax
movzwl (%rdi,%rax,2),%eax
mov    %ax,0x4(%rsi,%rcx,2)
movslq 0xc(%rdx,%rcx,4),%rax
movzwl 0xc8(%rdi,%rax,2),%eax
mov    %ax,0x6(%rsi,%rcx,2)
add    $0x4,%rcx
add    $0x320,%rdi
cmp    %rcx,%r10
jne    1180 <eval_ccga+0x70>
test   %r9,%r9
je     120d <eval_ccga+0xfd>
lea    (%rsi,%rcx,2),%r10
imul   $0xc8,%rcx,%rdi
add    %rbx,%rdi
lea    (%rdx,%rcx,4),%rcx
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
movslq (%rcx,%rdx,4),%rax
movzwl (%rdi,%rax,2),%eax
mov    %ax,(%r10,%rdx,2)
add    $0x1,%rdx
add    $0xc8,%rdi
cmp    %rdx,%r9
jne    11f0 <eval_ccga+0xe0>
cmpl   $0x0,-0x2c(%rbp)
jle    129b <eval_ccga+0x18b>
mov    -0x2c(%rbp),%eax
add    %eax,%eax
mov    %eax,-0x2c(%rbp)
xor    %eax,%eax
mov    %r11,-0x48(%rbp)
mov    %rsi,-0x40(%rbp)
mov    -0x50(%rbp),%r15
nopl   (%rax)
mov    %rbx,-0x38(%rbp)
mov    %r13,%rdi
mov    -0x2c(%rbp),%edx
mov    %rax,%rbx
call   1030 <memcpy@plt>
xor    %r14d,%r14d
cs nopw 0x0(%rax,%rax,1)
nop
mov    -0x38(%rbp),%rax
movzwl (%rax,%r14,2),%eax
mov    %ax,0x0(%r13,%rbx,2)
mov    %r13,%rdi
call   *%r15
movsd  %xmm0,(%r12,%r14,8)
add    $0x1,%r14
cmp    $0x64,%r14
jne    1250 <eval_ccga+0x140>
mov    %rbx,%rax
add    $0x1,%rax
add    $0x320,%r12
mov    -0x38(%rbp),%rbx
add    $0xc8,%rbx
mov    -0x48(%rbp),%r11
cmp    %r11,%rax
mov    -0x40(%rbp),%rsi
jne    1230 <eval_ccga+0x120>
lea    -0x28(%rbp),%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @eval_ccga(i32 %0, [100 x i16]* %1, i32* %2, double (i16*)* %3, [100 x double]* %4) {
%6 = alloca i32
%7 = alloca [100 x i16]*
%8 = alloca i32*
%9 = alloca double (i16*)*
%10 = alloca [100 x double]*
%11 = alloca i8*
%12 = alloca i64
%13 = alloca i64
%14 = alloca i32
%15 = alloca i32
%16 = alloca i32
store i32 %0, i32* %6
store [100 x i16]* %1, [100 x i16]** %7
store i32* %2, i32** %8
store double (i16*)* %3, double (i16*)** %9
store [100 x double]* %4, [100 x double]** %10
%17 = load i32, i32* %6
%18 = zext i32 %17 to i64
%19 = load i32, i32* %6
%20 = zext i32 %19 to i64
%21 = load i32, i32* %6
%22 = zext i32 %21 to i64
%23 = load i32, i32* %6
%24 = zext i32 %23 to i64
%25 = call i8* @llvm.stacksave()
store i8* %25, i8** %11
%26 = alloca i16, i64 %24
store i64 %24, i64* %12
%27 = load i32, i32* %6
%28 = zext i32 %27 to i64
%29 = alloca i16, i64 %28
store i64 %28, i64* %13
store i32 0, i32* %14
br label %30
30: ; preds = %50, %5
%31 = load i32, i32* %14
%32 = load i32, i32* %6
%33 = icmp slt i32 %31, %32
br i1 %33, label %34, label %53
34: ; preds = %30
%35 = load [100 x i16]*, [100 x i16]** %7
%36 = load i32, i32* %14
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds [100 x i16], [100 x i16]* %35, i64 %37
%39 = load i32*, i32** %8
%40 = load i32, i32* %14
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds i32, i32* %39, i64 %41
%43 = load i32, i32* %42
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds [100 x i16], [100 x i16]* %38, i64 0, i64 %44
%46 = load i16, i16* %45
%47 = load i32, i32* %14
%48 = sext i32 %47 to i64
%49 = getelementptr inbounds i16, i16* %26, i64 %48
store i16 %46, i16* %49
br label %50
50: ; preds = %34
%51 = load i32, i32* %14
%52 = add nsw i32 %51, 1
store i32 %52, i32* %14
br label %30
53: ; preds = %30
store i32 0, i32* %15
br label %54
54: ; preds = %94, %53
%55 = load i32, i32* %15
%56 = load i32, i32* %6
%57 = icmp slt i32 %55, %56
br i1 %57, label %58, label %97
58: ; preds = %54
%59 = bitcast i16* %29 to i16**
%60 = bitcast i16* %26 to i16**
%61 = load i32, i32* %6
%62 = sext i32 %61 to i64
%63 = mul i64 2, %62
%64 = trunc i64 %63 to i32
%65 = call i32 @memcpy(i16** %59, i16** %60, i32 %64)
store i32 0, i32* %16
br label %66
66: ; preds = %90, %58
%67 = load i32, i32* %16
%68 = icmp slt i32 %67, 100
br i1 %68, label %69, label %93
69: ; preds = %66
%70 = load [100 x i16]*, [100 x i16]** %7
%71 = load i32, i32* %15
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [100 x i16], [100 x i16]* %70, i64 %72
%74 = load i32, i32* %16
%75 = sext i32 %74 to i64
%76 = getelementptr inbounds [100 x i16], [100 x i16]* %73, i64 0, i64 %75
%77 = load i16, i16* %76
%78 = load i32, i32* %15
%79 = sext i32 %78 to i64
%80 = getelementptr inbounds i16, i16* %29, i64 %79
store i16 %77, i16* %80
%81 = load double (i16*)*, double (i16*)** %9
%82 = call double %81(i16* %29)
%83 = load [100 x double]*, [100 x double]** %10
%84 = load i32, i32* %15
%85 = sext i32 %84 to i64
%86 = getelementptr inbounds [100 x double], [100 x double]* %83, i64 %85
%87 = load i32, i32* %16
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds [100 x double], [100 x double]* %86, i64 0, i64 %88
store double %82, double* %89
br label %90
90: ; preds = %69
%91 = load i32, i32* %16
%92 = add nsw i32 %91, 1
store i32 %92, i32* %16
br label %66
93: ; preds = %66
br label %94
94: ; preds = %93
%95 = load i32, i32* %15
%96 = add nsw i32 %95, 1
store i32 %96, i32* %15
br label %54
97: ; preds = %54
%98 = load i8*, i8** %11
ret void
}

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