#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 */
double _logsumexp_sort_kahan_inplace(double *, int);
extern void _wham_update_therm_energies(double *conf_energies,
                                        double *bias_energies,
                                        int n_therm_states, int n_conf_states,
                                        double *scratch_M,
                                        double *therm_energies) {
  int i, K, KM;
  for (K = 0; K < n_therm_states; ++K) {
    KM = K * n_conf_states;
    for (i = 0; i < n_conf_states; ++i)
      scratch_M[i] = -(bias_energies[KM + i] + conf_energies[i]);
    therm_energies[K] =
        -_logsumexp_sort_kahan_inplace(scratch_M, n_conf_states);
  }
}


x86 assembly (clang, -O0):
<_wham_update_therm_energies>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11ed <_wham_update_therm_energies+0xdd>
mov    -0x30(%rbp),%eax
imul   -0x18(%rbp),%eax
mov    %eax,-0x34(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x18(%rbp),%eax
jge    11af <_wham_update_therm_energies+0x9f>
mov    -0x10(%rbp),%rax
mov    -0x34(%rbp),%ecx
add    -0x2c(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1152 <_wham_update_therm_energies+0x42>
mov    -0x20(%rbp),%rdi
mov    -0x18(%rbp),%esi
call   1030 <_logsumexp_sort_kahan_inplace@plt>
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x28(%rbp),%rax
movslq -0x30(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1135 <_wham_update_therm_energies+0x25>
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_wham_update_therm_energies>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x68,%rsp
mov    %r9,0x58(%rsp)
mov    %rsi,0x8(%rsp)
test   %edx,%edx
jle    13c8 <_wham_update_therm_energies+0x2b8>
mov    %r8,%rbx
mov    %ecx,%r12d
mov    %rdi,%rbp
movslq %ecx,%rcx
mov    %edx,%eax
mov    %rax,0x50(%rsp)
mov    %ecx,%r14d
lea    (%r8,%r14,8),%rdx
lea    (%rdi,%r14,8),%rax
mov    %r14d,%esi
and    $0xfffffffc,%esi
mov    %rsi,0x28(%rsp)
add    $0xfffffffffffffffc,%rsi
mov    %rsi,0x20(%rsp)
shr    $0x2,%rsi
add    $0x1,%rsi
cmp    %r8,%rax
seta   %al
mov    %rdx,0x30(%rsp)
cmp    %rdi,%rdx
seta   %dl
and    %al,%dl
mov    %dl,0x7(%rsp)
mov    %rsi,%rax
mov    %rsi,0x18(%rsp)
and    $0xfffffffffffffffe,%rsi
mov    %rsi,0x10(%rsp)
mov    %r14,%rax
neg    %rax
mov    %rax,0x38(%rsp)
mov    0x8(%rsp),%rax
lea    0x30(%rax),%r13
mov    %rcx,0x40(%rsp)
lea    0x0(,%rcx,8),%rcx
mov    %rcx,0x48(%rsp)
lea    0x8(%rax),%r15
xor    %edi,%edi
movapd 0xe3a(%rip),%xmm3
movapd 0xe32(%rip),%xmm4
jmp    121d <_wham_update_therm_energies+0x10d>
mov    %rdi,0x60(%rsp)
mov    %rbx,%rdi
mov    %r12d,%esi
call   1030 <_logsumexp_sort_kahan_inplace@plt>
movapd 0xe18(%rip),%xmm4
movapd 0xe10(%rip),%xmm3
mov    0x60(%rsp),%rdi
xorpd  %xmm4,%xmm0
mov    0x58(%rsp),%rax
movlpd %xmm0,(%rax,%rdi,8)
add    $0x1,%rdi
mov    0x48(%rsp),%rax
add    %rax,%r13
add    %rax,%r15
cmp    0x50(%rsp),%rdi
je     13c8 <_wham_update_therm_energies+0x2b8>
test   %r12d,%r12d
jle    11d0 <_wham_update_therm_energies+0xc0>
mov    %rdi,%rax
imul   0x40(%rsp),%rax
cmp    $0x4,%r12d
jb     125c <_wham_update_therm_energies+0x14c>
lea    (%rax,%r14,1),%rcx
mov    0x8(%rsp),%rsi
lea    (%rsi,%rax,8),%rdx
lea    (%rsi,%rcx,8),%rcx
cmp    %rbx,%rcx
seta   %cl
cmp    0x30(%rsp),%rdx
setb   %dl
and    %cl,%dl
or     0x7(%rsp),%dl
je     12da <_wham_update_therm_energies+0x1ca>
xor    %edx,%edx
mov    %rdx,%rcx
test   $0x1,%r14b
je     128a <_wham_update_therm_energies+0x17a>
add    %rdx,%rax
mov    0x8(%rsp),%rcx
movsd  (%rcx,%rax,8),%xmm0
addsd  0x0(%rbp,%rdx,8),%xmm0
xorpd  %xmm4,%xmm0
movlpd %xmm0,(%rbx,%rdx,8)
mov    %rdx,%rcx
or     $0x1,%rcx
not    %rdx
cmp    0x38(%rsp),%rdx
je     11d0 <_wham_update_therm_energies+0xc0>
nopl   0x0(%rax,%rax,1)
movsd  -0x8(%r15,%rcx,8),%xmm0
addsd  0x0(%rbp,%rcx,8),%xmm0
xorpd  %xmm3,%xmm0
movlpd %xmm0,(%rbx,%rcx,8)
movsd  (%r15,%rcx,8),%xmm0
addsd  0x8(%rbp,%rcx,8),%xmm0
xorpd  %xmm3,%xmm0
movlpd %xmm0,0x8(%rbx,%rcx,8)
add    $0x2,%rcx
cmp    %rcx,%r14
jne    12a0 <_wham_update_therm_energies+0x190>
jmp    11d0 <_wham_update_therm_energies+0xc0>
cmpq   $0x0,0x20(%rsp)
je     13bd <_wham_update_therm_energies+0x2ad>
mov    0x10(%rsp),%rdx
xor    %ecx,%ecx
nopl   (%rax)
movupd -0x30(%r13,%rcx,8),%xmm0
movupd -0x20(%r13,%rcx,8),%xmm1
movupd 0x0(%rbp,%rcx,8),%xmm2
addpd  %xmm0,%xmm2
movupd 0x10(%rbp,%rcx,8),%xmm0
addpd  %xmm1,%xmm0
xorpd  %xmm4,%xmm2
xorpd  %xmm4,%xmm0
movupd %xmm2,(%rbx,%rcx,8)
movupd %xmm0,0x10(%rbx,%rcx,8)
movupd -0x10(%r13,%rcx,8),%xmm0
movupd 0x0(%r13,%rcx,8),%xmm1
movupd 0x20(%rbp,%rcx,8),%xmm2
addpd  %xmm0,%xmm2
movupd 0x30(%rbp,%rcx,8),%xmm0
addpd  %xmm1,%xmm0
xorpd  %xmm4,%xmm2
xorpd  %xmm4,%xmm0
movupd %xmm2,0x20(%rbx,%rcx,8)
movupd %xmm0,0x30(%rbx,%rcx,8)
add    $0x8,%rcx
add    $0xfffffffffffffffe,%rdx
jne    12f0 <_wham_update_therm_energies+0x1e0>
testb  $0x1,0x18(%rsp)
je     13a7 <_wham_update_therm_energies+0x297>
lea    (%rcx,%rax,1),%rdx
mov    0x8(%rsp),%rsi
movupd (%rsi,%rdx,8),%xmm0
movupd 0x10(%rsi,%rdx,8),%xmm1
movupd 0x0(%rbp,%rcx,8),%xmm2
addpd  %xmm0,%xmm2
movupd 0x10(%rbp,%rcx,8),%xmm0
addpd  %xmm1,%xmm0
xorpd  %xmm4,%xmm2
xorpd  %xmm4,%xmm0
movupd %xmm2,(%rbx,%rcx,8)
movupd %xmm0,0x10(%rbx,%rcx,8)
mov    0x28(%rsp),%rcx
mov    %rcx,%rdx
cmp    %r14,%rcx
je     11d0 <_wham_update_therm_energies+0xc0>
jmp    125e <_wham_update_therm_energies+0x14e>
xor    %ecx,%ecx
testb  $0x1,0x18(%rsp)
jne    136c <_wham_update_therm_energies+0x25c>
jmp    13a7 <_wham_update_therm_energies+0x297>
add    $0x68,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @_wham_update_therm_energies(double* %0, double* %1, i32 %2, i32 %3, double* %4, double* %5) {
%7 = alloca double*
%8 = alloca double*
%9 = alloca i32
%10 = alloca i32
%11 = alloca double*
%12 = alloca double*
%13 = alloca i32
%14 = alloca i32
%15 = alloca i32
store double* %0, double** %7
store double* %1, double** %8
store i32 %2, i32* %9
store i32 %3, i32* %10
store double* %4, double** %11
store double* %5, double** %12
store i32 0, i32* %14
br label %16
16: ; preds = %59, %6
%17 = load i32, i32* %14
%18 = load i32, i32* %9
%19 = icmp slt i32 %17, %18
br i1 %19, label %20, label %62
20: ; preds = %16
%21 = load i32, i32* %14
%22 = load i32, i32* %10
%23 = mul nsw i32 %21, %22
store i32 %23, i32* %15
store i32 0, i32* %13
br label %24
24: ; preds = %47, %20
%25 = load i32, i32* %13
%26 = load i32, i32* %10
%27 = icmp slt i32 %25, %26
br i1 %27, label %28, label %50
28: ; preds = %24
%29 = load double*, double** %8
%30 = load i32, i32* %15
%31 = load i32, i32* %13
%32 = add nsw i32 %30, %31
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds double, double* %29, i64 %33
%35 = load double, double* %34
%36 = load double*, double** %7
%37 = load i32, i32* %13
%38 = sext i32 %37 to i64
%39 = getelementptr inbounds double, double* %36, i64 %38
%40 = load double, double* %39
%41 = fadd double %35, %40
%42 = fneg double %41
%43 = load double*, double** %11
%44 = load i32, i32* %13
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds double, double* %43, i64 %45
store double %42, double* %46
br label %47
47: ; preds = %28
%48 = load i32, i32* %13
%49 = add nsw i32 %48, 1
store i32 %49, i32* %13
br label %24
50: ; preds = %24
%51 = load double*, double** %11
%52 = load i32, i32* %10
%53 = call double @_logsumexp_sort_kahan_inplace(double* %51, i32 %52)
%54 = fneg double %53
%55 = load double*, double** %12
%56 = load i32, i32* %14
%57 = sext i32 %56 to i64
%58 = getelementptr inbounds double, double* %55, i64 %57
store double %54, double* %58
br label %59
59: ; preds = %50
%60 = load i32, i32* %14
%61 = add nsw i32 %60, 1
store i32 %61, i32* %14
br label %16
62: ; preds = %16
ret void
}

LLVM IR (-O2):
define void @_wham_update_therm_energies(double* nocapture %0, double* nocapture %1, i32 %2, i32 %3, double* %4, double* nocapture writeonly %5) {
%7 = icmp sgt i32 %2, 0
br i1 %7, label %8, label %163
8: ; preds = %6
%9 = icmp sgt i32 %3, 0
%10 = sext i32 %3 to i64
%11 = zext i32 %2 to i64
%12 = zext i32 %3 to i64
%13 = getelementptr double, double* %4, i64 %12
%14 = getelementptr double, double* %0, i64 %12
%15 = and i64 %12, 4294967292
%16 = add nsw i64 %15, -4
%17 = lshr exact i64 %16, 2
%18 = add nuw nsw i64 %17, 1
%19 = icmp ult i32 %3, 4
%20 = icmp ugt double* %14, %4
%21 = icmp ugt double* %13, %0
%22 = and i1 %20, %21
%23 = and i64 %12, 4294967292
%24 = and i64 %18, 1
%25 = icmp eq i64 %16, 0
%26 = and i64 %18, 9223372036854775806
%27 = icmp eq i64 %24, 0
%28 = icmp eq i64 %23, %12
%29 = and i64 %12, 1
%30 = icmp eq i64 %29, 0
%31 = sub nsw i64 0, %12
br label %32
32: ; preds = %8, %157
%33 = phi i64 [ 0, %8 ], [ %161, %157 ]
%34 = mul i64 %33, %10
%35 = getelementptr double, double* %1, i64 %34
%36 = add i64 %34, %12
%37 = getelementptr double, double* %1, i64 %36
%38 = mul nsw i64 %33, %10
br i1 %9, label %39, label %157
39: ; preds = %32
br i1 %19, label %120, label %40
40: ; preds = %39
%41 = icmp ugt double* %37, %4
%42 = icmp ult double* %35, %13
%43 = and i1 %41, %42
%44 = or i1 %43, %22
br i1 %44, label %120, label %45
45: ; preds = %40
br i1 %25, label %95, label %46
46: ; preds = %45, %46
%47 = phi i64 [ %92, %46 ], [ 0, %45 ]
%48 = phi i64 [ %93, %46 ], [ 0, %45 ]
%49 = add nsw i64 %47, %38
%50 = getelementptr inbounds double, double* %1, i64 %49
%51 = bitcast double* %50 to <2 x double>*
%52 = load <2 x double>, <2 x double>* %51
%53 = getelementptr inbounds double, double* %50, i64 2
%54 = bitcast double* %53 to <2 x double>*
%55 = load <2 x double>, <2 x double>* %54
%56 = getelementptr inbounds double, double* %0, i64 %47
%57 = bitcast double* %56 to <2 x double>*
%58 = load <2 x double>, <2 x double>* %57
%59 = getelementptr inbounds double, double* %56, i64 2
%60 = bitcast double* %59 to <2 x double>*
%61 = load <2 x double>, <2 x double>* %60
%62 = fadd <2 x double> %52, %58
%63 = fadd <2 x double> %55, %61
%64 = fneg <2 x double> %62
%65 = fneg <2 x double> %63
%66 = getelementptr inbounds double, double* %4, i64 %47
%67 = bitcast double* %66 to <2 x double>*
store <2 x double> %64, <2 x double>* %67
%68 = getelementptr inbounds double, double* %66, i64 2
%69 = bitcast double* %68 to <2 x double>*
store <2 x double> %65, <2 x double>* %69
%70 = or i64 %47, 4
%71 = add nsw i64 %70, %38
%72 = getelementptr inbounds double, double* %1, i64 %71
%73 = bitcast double* %72 to <2 x double>*
%74 = load <2 x double>, <2 x double>* %73
%75 = getelementptr inbounds double, double* %72, i64 2
%76 = bitcast double* %75 to <2 x double>*
%77 = load <2 x double>, <2 x double>* %76
%78 = getelementptr inbounds double, double* %0, i64 %70
%79 = bitcast double* %78 to <2 x double>*
%80 = load <2 x double>, <2 x double>* %79
%81 = getelementptr inbounds double, double* %78, i64 2
%82 = bitcast double* %81 to <2 x double>*
%83 = load <2 x double>, <2 x double>* %82
%84 = fadd <2 x double> %74, %80
%85 = fadd <2 x double> %77, %83
%86 = fneg <2 x double> %84
%87 = fneg <2 x double> %85
%88 = getelementptr inbounds double, double* %4, i64 %70
%89 = bitcast double* %88 to <2 x double>*
store <2 x double> %86, <2 x double>* %89
%90 = getelementptr inbounds double, double* %88, i64 2
%91 = bitcast double* %90 to <2 x double>*
store <2 x double> %87, <2 x double>* %91
%92 = add nuw i64 %47, 8
%93 = add i64 %48, 2
%94 = icmp eq i64 %93, %26
br i1 %94, label %95, label %46
95: ; preds = %46, %45
%96 = phi i64 [ 0, %45 ], [ %92, %46 ]
br i1 %27, label %119, label %97
97: ; preds = %95
%98 = add nsw i64 %96, %38
%99 = getelementptr inbounds double, double* %1, i64 %98
%100 = bitcast double* %99 to <2 x double>*
%101 = load <2 x double>, <2 x double>* %100
%102 = getelementptr inbounds double, double* %99, i64 2
%103 = bitcast double* %102 to <2 x double>*
%104 = load <2 x double>, <2 x double>* %103
%105 = getelementptr inbounds double, double* %0, i64 %96
%106 = bitcast double* %105 to <2 x double>*
%107 = load <2 x double>, <2 x double>* %106
%108 = getelementptr inbounds double, double* %105, i64 2
%109 = bitcast double* %108 to <2 x double>*
%110 = load <2 x double>, <2 x double>* %109
%111 = fadd <2 x double> %101, %107
%112 = fadd <2 x double> %104, %110
%113 = fneg <2 x double> %111
%114 = fneg <2 x double> %112
%115 = getelementptr inbounds double, double* %4, i64 %96
%116 = bitcast double* %115 to <2 x double>*
store <2 x double> %113, <2 x double>* %116
%117 = getelementptr inbounds double, double* %115, i64 2
%118 = bitcast double* %117 to <2 x double>*
store <2 x double> %114, <2 x double>* %118
br label %119
119: ; preds = %95, %97
br i1 %28, label %157, label %120
120: ; preds = %40, %39, %119
%121 = phi i64 [ 0, %40 ], [ 0, %39 ], [ %23, %119 ]
%122 = xor i64 %121, -1
br i1 %30, label %133, label %123
123: ; preds = %120
%124 = add nsw i64 %121, %38
%125 = getelementptr inbounds double, double* %1, i64 %124
%126 = load double, double* %125
%127 = getelementptr inbounds double, double* %0, i64 %121
%128 = load double, double* %127
%129 = fadd double %126, %128
%130 = fneg double %129
%131 = getelementptr inbounds double, double* %4, i64 %121
store double %130, double* %131
%132 = or i64 %121, 1
br label %133
133: ; preds = %123, %120
%134 = phi i64 [ %121, %120 ], [ %132, %123 ]
%135 = icmp eq i64 %122, %31
br i1 %135, label %157, label %136
136: ; preds = %133, %136
%137 = phi i64 [ %155, %136 ], [ %134, %133 ]
%138 = add nsw i64 %137, %38
%139 = getelementptr inbounds double, double* %1, i64 %138
%140 = load double, double* %139
%141 = getelementptr inbounds double, double* %0, i64 %137
%142 = load double, double* %141
%143 = fadd double %140, %142
%144 = fneg double %143
%145 = getelementptr inbounds double, double* %4, i64 %137
store double %144, double* %145
%146 = add nuw nsw i64 %137, 1
%147 = add nsw i64 %146, %38
%148 = getelementptr inbounds double, double* %1, i64 %147
%149 = load double, double* %148
%150 = getelementptr inbounds double, double* %0, i64 %146
%151 = load double, double* %150
%152 = fadd double %149, %151
%153 = fneg double %152
%154 = getelementptr inbounds double, double* %4, i64 %146
store double %153, double* %154
%155 = add nuw nsw i64 %137, 2
%156 = icmp eq i64 %155, %12
br i1 %156, label %157, label %136
157: ; preds = %133, %136, %119, %32
%158 = tail call double @_logsumexp_sort_kahan_inplace(double* %4, i32 %3)
%159 = fneg double %158
%160 = getelementptr inbounds double, double* %5, i64 %33
store double %159, double* %160
%161 = add nuw nsw i64 %33, 1
%162 = icmp eq i64 %161, %11
br i1 %162, label %163, label %32
163: ; preds = %157, %6
ret void
}