#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 mlnL(double *, double **, double **, int);
double rxn_coor(double *, double *, int);
double tanh(double);
double grad(double *a, double **zA, double **zB, double *dmlnL, int m) {
  int i, j, k;
  double lnl, rk, C;
  lnl = -mlnL(a, zA, zB, m);
  for (i = 0; i <= m; i = i + 1) {
    dmlnL[i] = 0.0;
  }
  for (i = 1; i <= zA[0][0]; i = i + 1) {
    rk = rxn_coor(a, zA[i], m);
    C = 1.0 + tanh(rk);
    dmlnL[0] = dmlnL[0] + C;
    for (j = 1; j <= m; j = j + 1) {
      dmlnL[j] = dmlnL[j] + C * zA[i][j];
    }
  }
  for (i = 1; i <= zB[0][0]; i = i + 1) {
    rk = rxn_coor(a, zB[i], m);
    C = 1.0 - tanh(rk);
    dmlnL[0] = dmlnL[0] - C;
    for (j = 1; j <= m; j = j + 1) {
      dmlnL[j] = dmlnL[j] - C * zB[i][j];
    }
  }
  return (-lnl);
}


x86 assembly (clang, -O0):
<grad>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8d,-0x24(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    -0x18(%rbp),%rdx
mov    -0x24(%rbp),%ecx
call   1050 <mlnL@plt>
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x38(%rbp)
movl   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0x24(%rbp),%eax
jg     11ad <grad+0x7d>
mov    -0x20(%rbp),%rax
movslq -0x28(%rbp),%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1183 <grad+0x53>
movl   $0x1,-0x28(%rbp)
cvtsi2sdl -0x28(%rbp),%xmm1
mov    -0x10(%rbp),%rax
mov    (%rax),%rax
movsd  (%rax),%xmm0
ucomisd %xmm1,%xmm0
jb     128e <grad+0x15e>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rax
movslq -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rsi
mov    -0x24(%rbp),%edx
call   1040 <rxn_coor@plt>
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm0
call   1030 <tanh@plt>
movaps %xmm0,%xmm1
movsd  0xe00(%rip),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
addsd  -0x48(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
movl   $0x1,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jg     127b <grad+0x14b>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x48(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%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    1225 <grad+0xf5>
jmp    1280 <grad+0x150>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    11b4 <grad+0x84>
movl   $0x1,-0x28(%rbp)
cvtsi2sdl -0x28(%rbp),%xmm1
mov    -0x18(%rbp),%rax
mov    (%rax),%rax
movsd  (%rax),%xmm0
ucomisd %xmm1,%xmm0
jb     1386 <grad+0x256>
mov    -0x8(%rbp),%rdi
mov    -0x18(%rbp),%rax
movslq -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rsi
mov    -0x24(%rbp),%edx
call   1040 <rxn_coor@plt>
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm0
call   1030 <tanh@plt>
movaps %xmm0,%xmm1
movsd  0xd1f(%rip),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
subsd  -0x48(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
movl   $0x1,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jg     1373 <grad+0x243>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x48(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%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    1306 <grad+0x1d6>
jmp    1378 <grad+0x248>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1295 <grad+0x165>
movsd  -0x38(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<grad>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x68,%rsp
mov    %r8d,%r12d
mov    %rcx,%rbx
mov    %rdx,%r14
mov    %rsi,%rbp
mov    %rdi,0x50(%rsp)
mov    %r8d,%ecx
call   1060 <mlnL@plt>
movsd  %xmm0,0x60(%rsp)
mov    %r12d,%r15d
test   %r12d,%r12d
js     1187 <grad+0x47>
lea    0x8(,%r15,8),%rdx
mov    %rbx,%rdi
xor    %esi,%esi
call   1040 <memset@plt>
mov    %r15,0x8(%rsp)
movabs $0x7ffffffffffffffe,%rax
ff ff 7f
mov    %rax,0x48(%rsp)
mov    0x0(%rbp),%rax
movsd  (%rax),%xmm0
ucomisd 0xe55(%rip),%xmm0
jae    11dc <grad+0x9c>
mov    (%r14),%rax
movsd  (%rax),%xmm0
ucomisd 0xe44(%rip),%xmm0
mov    0x8(%rsp),%r15
jae    1427 <grad+0x2e7>
movsd  0x60(%rsp),%xmm0
add    $0x68,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
mov    0x8(%rsp),%rax
lea    0x1(%rax),%r13
lea    0x8(%rbx),%rcx
mov    %rcx,0x38(%rsp)
lea    (%rbx,%rax,8),%rcx
add    $0x8,%rcx
mov    %rcx,0x30(%rsp)
lea    -0x4(%rax),%rcx
mov    %rcx,0x28(%rsp)
mov    %rcx,%rdx
shr    $0x2,%rdx
add    $0x1,%rdx
mov    %eax,%ecx
and    $0xfffffffc,%ecx
mov    %rcx,0x18(%rsp)
add    $0x1,%rcx
mov    %rcx,0x10(%rsp)
mov    %rdx,%rcx
mov    %rdx,0x20(%rsp)
movabs $0x7ffffffffffffffe,%rcx
ff ff 7f
and    %rcx,%rdx
mov    %rdx,0x58(%rsp)
not    %rax
mov    %rax,0x40(%rsp)
mov    $0x1,%r15d
jmp    126e <grad+0x12e>
nopl   0x0(%rax)
add    $0x1,%r15
xorps  %xmm0,%xmm0
cvtsi2sd %r15d,%xmm0
mov    0x0(%rbp),%rax
movsd  (%rax),%xmm1
ucomisd %xmm0,%xmm1
jb     11ad <grad+0x6d>
mov    0x0(%rbp,%r15,8),%rsi
mov    0x50(%rsp),%rdi
mov    %r12d,%edx
call   1050 <rxn_coor@plt>
call   1030 <tanh@plt>
addsd  0xd73(%rip),%xmm0
movsd  (%rbx),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%rbx)
test   %r12d,%r12d
jle    1250 <grad+0x110>
mov    0x0(%rbp,%r15,8),%rax
mov    $0x1,%ecx
cmpl   $0x4,0x8(%rsp)
jb     13c0 <grad+0x280>
lea    (%rax,%r13,8),%rdx
cmp    %rdx,0x38(%rsp)
jae    12cd <grad+0x18d>
lea    0x8(%rax),%rdx
cmp    0x30(%rsp),%rdx
jb     13c0 <grad+0x280>
movapd %xmm0,%xmm1
unpcklpd %xmm0,%xmm1
cmpq   $0x4,0x28(%rsp)
jae    12e4 <grad+0x1a4>
xor    %ecx,%ecx
jmp    1362 <grad+0x222>
mov    0x58(%rsp),%rdx
xor    %ecx,%ecx
nopl   0x0(%rax,%rax,1)
movupd 0x8(%rax,%rcx,8),%xmm2
movupd 0x18(%rax,%rcx,8),%xmm3
mulpd  %xmm1,%xmm2
movupd 0x8(%rbx,%rcx,8),%xmm4
addpd  %xmm2,%xmm4
movupd 0x18(%rbx,%rcx,8),%xmm2
movupd 0x28(%rbx,%rcx,8),%xmm5
movupd 0x38(%rbx,%rcx,8),%xmm6
mulpd  %xmm1,%xmm3
addpd  %xmm2,%xmm3
movupd %xmm4,0x8(%rbx,%rcx,8)
movupd %xmm3,0x18(%rbx,%rcx,8)
movupd 0x28(%rax,%rcx,8),%xmm2
movupd 0x38(%rax,%rcx,8),%xmm3
mulpd  %xmm1,%xmm2
addpd  %xmm5,%xmm2
mulpd  %xmm1,%xmm3
addpd  %xmm6,%xmm3
movupd %xmm2,0x28(%rbx,%rcx,8)
movupd %xmm3,0x38(%rbx,%rcx,8)
add    $0x8,%rcx
add    $0xfffffffffffffffe,%rdx
jne    12f0 <grad+0x1b0>
testb  $0x1,0x20(%rsp)
je     13a2 <grad+0x262>
shl    $0x3,%rcx
or     $0x8,%rcx
movupd (%rbx,%rcx,1),%xmm2
movupd 0x10(%rbx,%rcx,1),%xmm3
movupd (%rax,%rcx,1),%xmm4
movupd 0x10(%rax,%rcx,1),%xmm5
mulpd  %xmm1,%xmm4
addpd  %xmm2,%xmm4
mulpd  %xmm1,%xmm5
addpd  %xmm3,%xmm5
movupd %xmm4,(%rbx,%rcx,1)
movupd %xmm5,0x10(%rbx,%rcx,1)
mov    0x10(%rsp),%rcx
mov    0x18(%rsp),%rdx
cmp    %rdx,0x8(%rsp)
je     1250 <grad+0x110>
nopw   0x0(%rax,%rax,1)
mov    %rcx,%rdx
test   $0x1,%r13b
jne    13e0 <grad+0x2a0>
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm0,%xmm1
addsd  (%rbx,%rcx,8),%xmm1
movsd  %xmm1,(%rbx,%rcx,8)
lea    0x1(%rcx),%rdx
not    %rcx
cmp    0x40(%rsp),%rcx
je     1250 <grad+0x110>
xchg   %ax,%ax
movsd  (%rax,%rdx,8),%xmm1
mulsd  %xmm0,%xmm1
addsd  (%rbx,%rdx,8),%xmm1
movsd  %xmm1,(%rbx,%rdx,8)
movsd  0x8(%rax,%rdx,8),%xmm1
mulsd  %xmm0,%xmm1
addsd  0x8(%rbx,%rdx,8),%xmm1
movsd  %xmm1,0x8(%rbx,%rdx,8)
add    $0x2,%rdx
cmp    %rdx,%r13
jne    13f0 <grad+0x2b0>
jmp    1250 <grad+0x110>
lea    0x1(%r15),%rbp
lea    0x8(%rbx),%rax
mov    %rax,0x38(%rsp)
lea    (%rbx,%r15,8),%rax
add    $0x8,%rax
mov    %rax,0x30(%rsp)
lea    -0x4(%r15),%rax
mov    %rax,0x28(%rsp)
shr    $0x2,%rax
add    $0x1,%rax
mov    %r15d,%ecx
and    $0xfffffffc,%ecx
mov    %rcx,0x18(%rsp)
add    $0x1,%rcx
mov    %rcx,0x10(%rsp)
mov    %rax,%rcx
mov    %rax,0x20(%rsp)
and    %rax,0x48(%rsp)
mov    %r15,%rax
not    %rax
mov    %rax,0x40(%rsp)
mov    $0x1,%r13d
jmp    14ad <grad+0x36d>
cs nopw 0x0(%rax,%rax,1)
add    $0x1,%r13
xorps  %xmm0,%xmm0
cvtsi2sd %r13d,%xmm0
mov    (%r14),%rax
movsd  (%rax),%xmm1
ucomisd %xmm0,%xmm1
jb     11c7 <grad+0x87>
mov    (%r14,%r13,8),%rsi
mov    0x50(%rsp),%rdi
mov    %r12d,%edx
call   1050 <rxn_coor@plt>
call   1030 <tanh@plt>
movsd  0xb35(%rip),%xmm1
subsd  %xmm0,%xmm1
movsd  (%rbx),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rbx)
test   %r12d,%r12d
jle    1490 <grad+0x350>
mov    (%r14,%r13,8),%rax
xorpd  0xb24(%rip),%xmm1
mov    $0x1,%ecx
cmp    $0x4,%r15d
jb     1610 <grad+0x4d0>
lea    (%rax,%rbp,8),%rdx
cmp    %rdx,0x38(%rsp)
jae    1515 <grad+0x3d5>
lea    0x8(%rax),%rdx
cmp    0x30(%rsp),%rdx
jb     1610 <grad+0x4d0>
movapd %xmm1,%xmm0
unpcklpd %xmm1,%xmm0
cmpq   $0x4,0x28(%rsp)
jae    152c <grad+0x3ec>
xor    %ecx,%ecx
jmp    15b2 <grad+0x472>
mov    0x48(%rsp),%rdx
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movupd 0x8(%rax,%rcx,8),%xmm2
movupd 0x18(%rax,%rcx,8),%xmm3
mulpd  %xmm0,%xmm2
movupd 0x8(%rbx,%rcx,8),%xmm4
addpd  %xmm2,%xmm4
movupd 0x18(%rbx,%rcx,8),%xmm2
movupd 0x28(%rbx,%rcx,8),%xmm5
movupd 0x38(%rbx,%rcx,8),%xmm6
mulpd  %xmm0,%xmm3
addpd  %xmm2,%xmm3
movupd %xmm4,0x8(%rbx,%rcx,8)
movupd %xmm3,0x18(%rbx,%rcx,8)
movupd 0x28(%rax,%rcx,8),%xmm2
movupd 0x38(%rax,%rcx,8),%xmm3
mulpd  %xmm0,%xmm2
addpd  %xmm5,%xmm2
mulpd  %xmm0,%xmm3
addpd  %xmm6,%xmm3
movupd %xmm2,0x28(%rbx,%rcx,8)
movupd %xmm3,0x38(%rbx,%rcx,8)
add    $0x8,%rcx
add    $0xfffffffffffffffe,%rdx
jne    1540 <grad+0x400>
testb  $0x1,0x20(%rsp)
je     15f2 <grad+0x4b2>
shl    $0x3,%rcx
or     $0x8,%rcx
movupd (%rbx,%rcx,1),%xmm2
movupd 0x10(%rbx,%rcx,1),%xmm3
movupd (%rax,%rcx,1),%xmm4
movupd 0x10(%rax,%rcx,1),%xmm5
mulpd  %xmm0,%xmm4
addpd  %xmm2,%xmm4
mulpd  %xmm0,%xmm5
addpd  %xmm3,%xmm5
movupd %xmm4,(%rbx,%rcx,1)
movupd %xmm5,0x10(%rbx,%rcx,1)
mov    0x10(%rsp),%rcx
cmp    0x18(%rsp),%r15
je     1490 <grad+0x350>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mov    %rcx,%rdx
test   $0x1,%bpl
jne    1630 <grad+0x4f0>
movsd  (%rax,%rcx,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  (%rbx,%rcx,8),%xmm0
movsd  %xmm0,(%rbx,%rcx,8)
lea    0x1(%rcx),%rdx
not    %rcx
cmp    0x40(%rsp),%rcx
je     1490 <grad+0x350>
xchg   %ax,%ax
movsd  (%rax,%rdx,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  (%rbx,%rdx,8),%xmm0
movsd  %xmm0,(%rbx,%rdx,8)
movsd  0x8(%rax,%rdx,8),%xmm0
mulsd  %xmm1,%xmm0
addsd  0x8(%rbx,%rdx,8),%xmm0
movsd  %xmm0,0x8(%rbx,%rdx,8)
add    $0x2,%rdx
cmp    %rdx,%rbp
jne    1640 <grad+0x500>
jmp    1490 <grad+0x350>

LLVM IR (-O0):
define double @grad(double* %0, double** %1, double** %2, double* %3, i32 %4) {
%6 = alloca double*
%7 = alloca double**
%8 = alloca double**
%9 = alloca double*
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca double
%15 = alloca double
%16 = alloca double
store double* %0, double** %6
store double** %1, double*** %7
store double** %2, double*** %8
store double* %3, double** %9
store i32 %4, i32* %10
%17 = load double*, double** %6
%18 = load double**, double*** %7
%19 = load double**, double*** %8
%20 = load i32, i32* %10
%21 = call double @mlnL(double* %17, double** %18, double** %19, i32 %20)
%22 = fneg double %21
store double %22, double* %14
store i32 0, i32* %11
br label %23
23: ; preds = %32, %5
%24 = load i32, i32* %11
%25 = load i32, i32* %10
%26 = icmp sle i32 %24, %25
br i1 %26, label %27, label %35
27: ; preds = %23
%28 = load double*, double** %9
%29 = load i32, i32* %11
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds double, double* %28, i64 %30
store double 0.000000e+00, double* %31
br label %32
32: ; preds = %27
%33 = load i32, i32* %11
%34 = add nsw i32 %33, 1
store i32 %34, i32* %11
br label %23
35: ; preds = %23
store i32 1, i32* %11
br label %36
36: ; preds = %93, %35
%37 = load i32, i32* %11
%38 = sitofp i32 %37 to double
%39 = load double**, double*** %7
%40 = getelementptr inbounds double*, double** %39, i64 0
%41 = load double*, double** %40
%42 = getelementptr inbounds double, double* %41, i64 0
%43 = load double, double* %42
%44 = fcmp ole double %38, %43
br i1 %44, label %45, label %96
45: ; preds = %36
%46 = load double*, double** %6
%47 = load double**, double*** %7
%48 = load i32, i32* %11
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds double*, double** %47, i64 %49
%51 = load double*, double** %50
%52 = load i32, i32* %10
%53 = call double @rxn_coor(double* %46, double* %51, i32 %52)
store double %53, double* %15
%54 = load double, double* %15
%55 = call double @tanh(double %54)
%56 = fadd double 1.000000e+00, %55
store double %56, double* %16
%57 = load double*, double** %9
%58 = getelementptr inbounds double, double* %57, i64 0
%59 = load double, double* %58
%60 = load double, double* %16
%61 = fadd double %59, %60
%62 = load double*, double** %9
%63 = getelementptr inbounds double, double* %62, i64 0
store double %61, double* %63
store i32 1, i32* %12
br label %64
64: ; preds = %89, %45
%65 = load i32, i32* %12
%66 = load i32, i32* %10
%67 = icmp sle i32 %65, %66
br i1 %67, label %68, label %92
68: ; preds = %64
%69 = load double*, double** %9
%70 = load i32, i32* %12
%71 = sext i32 %70 to i64
%72 = getelementptr inbounds double, double* %69, i64 %71
%73 = load double, double* %72
%74 = load double, double* %16
%75 = load double**, double*** %7
%76 = load i32, i32* %11
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds double*, double** %75, i64 %77
%79 = load double*, double** %78
%80 = load i32, i32* %12
%81 = sext i32 %80 to i64
%82 = getelementptr inbounds double, double* %79, i64 %81
%83 = load double, double* %82
%84 = call double @llvm.fmuladd.f64(double %74, double %83, double %73)
%85 = load double*, double** %9
%86 = load i32, i32* %12
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds double, double* %85, i64 %87
store double %84, double* %88
br label %89
89: ; preds = %68
%90 = load i32, i32* %12
%91 = add nsw i32 %90, 1
store i32 %91, i32* %12
br label %64
92: ; preds = %64
br label %93
93: ; preds = %92
%94 = load i32, i32* %11
%95 = add nsw i32 %94, 1
store i32 %95, i32* %11
br label %36
96: ; preds = %36
store i32 1, i32* %11
br label %97
97: ; preds = %155, %96
%98 = load i32, i32* %11
%99 = sitofp i32 %98 to double
%100 = load double**, double*** %8
%101 = getelementptr inbounds double*, double** %100, i64 0
%102 = load double*, double** %101
%103 = getelementptr inbounds double, double* %102, i64 0
%104 = load double, double* %103
%105 = fcmp ole double %99, %104
br i1 %105, label %106, label %158
106: ; preds = %97
%107 = load double*, double** %6
%108 = load double**, double*** %8
%109 = load i32, i32* %11
%110 = sext i32 %109 to i64
%111 = getelementptr inbounds double*, double** %108, i64 %110
%112 = load double*, double** %111
%113 = load i32, i32* %10
%114 = call double @rxn_coor(double* %107, double* %112, i32 %113)
store double %114, double* %15
%115 = load double, double* %15
%116 = call double @tanh(double %115)
%117 = fsub double 1.000000e+00, %116
store double %117, double* %16
%118 = load double*, double** %9
%119 = getelementptr inbounds double, double* %118, i64 0
%120 = load double, double* %119
%121 = load double, double* %16
%122 = fsub double %120, %121
%123 = load double*, double** %9
%124 = getelementptr inbounds double, double* %123, i64 0
store double %122, double* %124
store i32 1, i32* %12
br label %125
125: ; preds = %151, %106
%126 = load i32, i32* %12
%127 = load i32, i32* %10
%128 = icmp sle i32 %126, %127
br i1 %128, label %129, label %154
129: ; preds = %125
%130 = load double*, double** %9
%131 = load i32, i32* %12
%132 = sext i32 %131 to i64
%133 = getelementptr inbounds double, double* %130, i64 %132
%134 = load double, double* %133
%135 = load double, double* %16
%136 = load double**, double*** %8
%137 = load i32, i32* %11
%138 = sext i32 %137 to i64
%139 = getelementptr inbounds double*, double** %136, i64 %138
%140 = load double*, double** %139
%141 = load i32, i32* %12
%142 = sext i32 %141 to i64
%143 = getelementptr inbounds double, double* %140, i64 %142
%144 = load double, double* %143
%145 = fneg double %135
%146 = call double @llvm.fmuladd.f64(double %145, double %144, double %134)
%147 = load double*, double** %9
%148 = load i32, i32* %12
%149 = sext i32 %148 to i64
%150 = getelementptr inbounds double, double* %147, i64 %149
store double %146, double* %150
br label %151
151: ; preds = %129
%152 = load i32, i32* %12
%153 = add nsw i32 %152, 1
store i32 %153, i32* %12
br label %125
154: ; preds = %125
br label %155
155: ; preds = %154
%156 = load i32, i32* %11
%157 = add nsw i32 %156, 1
store i32 %157, i32* %11
br label %97
158: ; preds = %97
%159 = load double, double* %14
%160 = fneg double %159
ret double %160
}

LLVM IR (-O2):
define double @grad(double* %0, double** %1, double** %2, double* nocapture %3, i32 %4) {
%6 = tail call double @mlnL(double* %0, double** %1, double** %2, i32 %4)
%7 = icmp slt i32 %4, 0
br i1 %7, label %13, label %8
8: ; preds = %5
%9 = bitcast double* %3 to i8*
%10 = zext i32 %4 to i64
%11 = shl nuw nsw i64 %10, 3
%12 = add nuw nsw i64 %11, 8
br label %13
13: ; preds = %8, %5
%14 = load double*, double** %1
%15 = load double, double* %14
%16 = fcmp ult double %15, 1.000000e+00
br i1 %16, label %38, label %17
17: ; preds = %13
%18 = icmp slt i32 %4, 1
%19 = add nuw i32 %4, 1
%20 = zext i32 %19 to i64
%21 = getelementptr double, double* %3, i64 1
%22 = getelementptr double, double* %3, i64 %20
%23 = add nsw i64 %20, -1
%24 = add nsw i64 %20, -5
%25 = lshr i64 %24, 2
%26 = add nuw nsw i64 %25, 1
%27 = icmp ult i64 %23, 4
%28 = and i64 %23, -4
%29 = or i64 %28, 1
%30 = and i64 %26, 1
%31 = icmp ult i64 %24, 4
%32 = and i64 %26, 9223372036854775806
%33 = icmp eq i64 %30, 0
%34 = icmp eq i64 %23, %28
%35 = and i64 %20, 1
%36 = icmp eq i64 %35, 0
%37 = sub nsw i64 0, %20
br label %63
38: ; preds = %174, %13
%39 = load double*, double** %2
%40 = load double, double* %39
%41 = fcmp ult double %40, 1.000000e+00
br i1 %41, label %300, label %42
42: ; preds = %38
%43 = icmp slt i32 %4, 1
%44 = add nuw i32 %4, 1
%45 = zext i32 %44 to i64
%46 = getelementptr double, double* %3, i64 1
%47 = getelementptr double, double* %3, i64 %45
%48 = add nsw i64 %45, -1
%49 = add nsw i64 %45, -5
%50 = lshr i64 %49, 2
%51 = add nuw nsw i64 %50, 1
%52 = icmp ult i64 %48, 4
%53 = and i64 %48, -4
%54 = or i64 %53, 1
%55 = and i64 %51, 1
%56 = icmp ult i64 %49, 4
%57 = and i64 %51, 9223372036854775806
%58 = icmp eq i64 %55, 0
%59 = icmp eq i64 %48, %53
%60 = and i64 %45, 1
%61 = icmp eq i64 %60, 0
%62 = sub nsw i64 0, %45
br label %181
63: ; preds = %17, %174
%64 = phi i64 [ 1, %17 ], [ %175, %174 ]
%65 = getelementptr inbounds double*, double** %1, i64 %64
%66 = load double*, double** %65
%67 = tail call double @rxn_coor(double* %0, double* %66, i32 %4)
%68 = tail call double @tanh(double %67)
%69 = fadd double %68, 1.000000e+00
%70 = load double, double* %3
%71 = fadd double %70, %69
store double %71, double* %3
br i1 %18, label %174, label %72
72: ; preds = %63
%73 = load double*, double** %65
br i1 %27, label %146, label %74
74: ; preds = %72
%75 = getelementptr double, double* %73, i64 1
%76 = getelementptr double, double* %73, i64 %20
%77 = icmp ult double* %21, %76
%78 = icmp ult double* %75, %22
%79 = and i1 %77, %78
br i1 %79, label %146, label %80
80: ; preds = %74
%81 = insertelement <2 x double> poison, double %69, i64 0
%82 = shufflevector <2 x double> %81, <2 x double> poison, <2 x i32> zeroinitializer
%83 = insertelement <2 x double> poison, double %69, i64 0
%84 = shufflevector <2 x double> %83, <2 x double> poison, <2 x i32> zeroinitializer
br i1 %31, label %125, label %85
85: ; preds = %80, %85
%86 = phi i64 [ %122, %85 ], [ 0, %80 ]
%87 = phi i64 [ %123, %85 ], [ 0, %80 ]
%88 = or i64 %86, 1
%89 = getelementptr inbounds double, double* %3, i64 %88
%90 = bitcast double* %89 to <2 x double>*
%91 = load <2 x double>, <2 x double>* %90
%92 = getelementptr inbounds double, double* %89, i64 2
%93 = bitcast double* %92 to <2 x double>*
%94 = load <2 x double>, <2 x double>* %93
%95 = getelementptr inbounds double, double* %73, i64 %88
%96 = bitcast double* %95 to <2 x double>*
%97 = load <2 x double>, <2 x double>* %96
%98 = getelementptr inbounds double, double* %95, i64 2
%99 = bitcast double* %98 to <2 x double>*
%100 = load <2 x double>, <2 x double>* %99
%101 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %82, <2 x double> %97, <2 x double> %91)
%102 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %84, <2 x double> %100, <2 x double> %94)
%103 = bitcast double* %89 to <2 x double>*
store <2 x double> %101, <2 x double>* %103
%104 = bitcast double* %92 to <2 x double>*
store <2 x double> %102, <2 x double>* %104
%105 = or i64 %86, 5
%106 = getelementptr inbounds double, double* %3, i64 %105
%107 = bitcast double* %106 to <2 x double>*
%108 = load <2 x double>, <2 x double>* %107
%109 = getelementptr inbounds double, double* %106, i64 2
%110 = bitcast double* %109 to <2 x double>*
%111 = load <2 x double>, <2 x double>* %110
%112 = getelementptr inbounds double, double* %73, i64 %105
%113 = bitcast double* %112 to <2 x double>*
%114 = load <2 x double>, <2 x double>* %113
%115 = getelementptr inbounds double, double* %112, i64 2
%116 = bitcast double* %115 to <2 x double>*
%117 = load <2 x double>, <2 x double>* %116
%118 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %82, <2 x double> %114, <2 x double> %108)
%119 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %84, <2 x double> %117, <2 x double> %111)
%120 = bitcast double* %106 to <2 x double>*
store <2 x double> %118, <2 x double>* %120
%121 = bitcast double* %109 to <2 x double>*
store <2 x double> %119, <2 x double>* %121
%122 = add nuw i64 %86, 8
%123 = add i64 %87, 2
%124 = icmp eq i64 %123, %32
br i1 %124, label %125, label %85
125: ; preds = %85, %80
%126 = phi i64 [ 0, %80 ], [ %122, %85 ]
br i1 %33, label %145, label %127
127: ; preds = %125
%128 = or i64 %126, 1
%129 = getelementptr inbounds double, double* %3, i64 %128
%130 = bitcast double* %129 to <2 x double>*
%131 = load <2 x double>, <2 x double>* %130
%132 = getelementptr inbounds double, double* %129, i64 2
%133 = bitcast double* %132 to <2 x double>*
%134 = load <2 x double>, <2 x double>* %133
%135 = getelementptr inbounds double, double* %73, i64 %128
%136 = bitcast double* %135 to <2 x double>*
%137 = load <2 x double>, <2 x double>* %136
%138 = getelementptr inbounds double, double* %135, i64 2
%139 = bitcast double* %138 to <2 x double>*
%140 = load <2 x double>, <2 x double>* %139
%141 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %82, <2 x double> %137, <2 x double> %131)
%142 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %84, <2 x double> %140, <2 x double> %134)
%143 = bitcast double* %129 to <2 x double>*
store <2 x double> %141, <2 x double>* %143
%144 = bitcast double* %132 to <2 x double>*
store <2 x double> %142, <2 x double>* %144
br label %145
145: ; preds = %125, %127
br i1 %34, label %174, label %146
146: ; preds = %74, %72, %145
%147 = phi i64 [ 1, %74 ], [ 1, %72 ], [ %29, %145 ]
%148 = xor i64 %147, -1
br i1 %36, label %149, label %156
149: ; preds = %146
%150 = getelementptr inbounds double, double* %3, i64 %147
%151 = load double, double* %150
%152 = getelementptr inbounds double, double* %73, i64 %147
%153 = load double, double* %152
%154 = tail call double @llvm.fmuladd.f64(double %69, double %153, double %151)
store double %154, double* %150
%155 = add nuw nsw i64 %147, 1
br label %156
156: ; preds = %149, %146
%157 = phi i64 [ %147, %146 ], [ %155, %149 ]
%158 = icmp eq i64 %148, %37
br i1 %158, label %174, label %159
159: ; preds = %156, %159
%160 = phi i64 [ %172, %159 ], [ %157, %156 ]
%161 = getelementptr inbounds double, double* %3, i64 %160
%162 = load double, double* %161
%163 = getelementptr inbounds double, double* %73, i64 %160
%164 = load double, double* %163
%165 = tail call double @llvm.fmuladd.f64(double %69, double %164, double %162)
store double %165, double* %161
%166 = add nuw nsw i64 %160, 1
%167 = getelementptr inbounds double, double* %3, i64 %166
%168 = load double, double* %167
%169 = getelementptr inbounds double, double* %73, i64 %166
%170 = load double, double* %169
%171 = tail call double @llvm.fmuladd.f64(double %69, double %170, double %168)
store double %171, double* %167
%172 = add nuw nsw i64 %160, 2
%173 = icmp eq i64 %172, %20
br i1 %173, label %174, label %159
174: ; preds = %156, %159, %145, %63
%175 = add nuw i64 %64, 1
%176 = trunc i64 %175 to i32
%177 = sitofp i32 %176 to double
%178 = load double*, double** %1
%179 = load double, double* %178
%180 = fcmp ult double %179, %177
br i1 %180, label %38, label %63
181: ; preds = %42, %293
%182 = phi i64 [ 1, %42 ], [ %294, %293 ]
%183 = getelementptr inbounds double*, double** %2, i64 %182
%184 = load double*, double** %183
%185 = tail call double @rxn_coor(double* %0, double* %184, i32 %4)
%186 = tail call double @tanh(double %185)
%187 = fsub double 1.000000e+00, %186
%188 = load double, double* %3
%189 = fsub double %188, %187
store double %189, double* %3
br i1 %43, label %293, label %190
190: ; preds = %181
%191 = load double*, double** %183
%192 = fneg double %187
br i1 %52, label %265, label %193
193: ; preds = %190
%194 = getelementptr double, double* %191, i64 1
%195 = getelementptr double, double* %191, i64 %45
%196 = icmp ult double* %46, %195
%197 = icmp ult double* %194, %47
%198 = and i1 %196, %197
br i1 %198, label %265, label %199
199: ; preds = %193
%200 = insertelement <2 x double> poison, double %192, i64 0
%201 = shufflevector <2 x double> %200, <2 x double> poison, <2 x i32> zeroinitializer
%202 = insertelement <2 x double> poison, double %192, i64 0
%203 = shufflevector <2 x double> %202, <2 x double> poison, <2 x i32> zeroinitializer
br i1 %56, label %244, label %204
204: ; preds = %199, %204
%205 = phi i64 [ %241, %204 ], [ 0, %199 ]
%206 = phi i64 [ %242, %204 ], [ 0, %199 ]
%207 = or i64 %205, 1
%208 = getelementptr inbounds double, double* %3, i64 %207
%209 = bitcast double* %208 to <2 x double>*
%210 = load <2 x double>, <2 x double>* %209
%211 = getelementptr inbounds double, double* %208, i64 2
%212 = bitcast double* %211 to <2 x double>*
%213 = load <2 x double>, <2 x double>* %212
%214 = getelementptr inbounds double, double* %191, i64 %207
%215 = bitcast double* %214 to <2 x double>*
%216 = load <2 x double>, <2 x double>* %215
%217 = getelementptr inbounds double, double* %214, i64 2
%218 = bitcast double* %217 to <2 x double>*
%219 = load <2 x double>, <2 x double>* %218
%220 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %201, <2 x double> %216, <2 x double> %210)
%221 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %203, <2 x double> %219, <2 x double> %213)
%222 = bitcast double* %208 to <2 x double>*
store <2 x double> %220, <2 x double>* %222
%223 = bitcast double* %211 to <2 x double>*
store <2 x double> %221, <2 x double>* %223
%224 = or i64 %205, 5
%225 = getelementptr inbounds double, double* %3, i64 %224
%226 = bitcast double* %225 to <2 x double>*
%227 = load <2 x double>, <2 x double>* %226
%228 = getelementptr inbounds double, double* %225, i64 2
%229 = bitcast double* %228 to <2 x double>*
%230 = load <2 x double>, <2 x double>* %229
%231 = getelementptr inbounds double, double* %191, i64 %224
%232 = bitcast double* %231 to <2 x double>*
%233 = load <2 x double>, <2 x double>* %232
%234 = getelementptr inbounds double, double* %231, i64 2
%235 = bitcast double* %234 to <2 x double>*
%236 = load <2 x double>, <2 x double>* %235
%237 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %201, <2 x double> %233, <2 x double> %227)
%238 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %203, <2 x double> %236, <2 x double> %230)
%239 = bitcast double* %225 to <2 x double>*
store <2 x double> %237, <2 x double>* %239
%240 = bitcast double* %228 to <2 x double>*
store <2 x double> %238, <2 x double>* %240
%241 = add nuw i64 %205, 8
%242 = add i64 %206, 2
%243 = icmp eq i64 %242, %57
br i1 %243, label %244, label %204
244: ; preds = %204, %199
%245 = phi i64 [ 0, %199 ], [ %241, %204 ]
br i1 %58, label %264, label %246
246: ; preds = %244
%247 = or i64 %245, 1
%248 = getelementptr inbounds double, double* %3, i64 %247
%249 = bitcast double* %248 to <2 x double>*
%250 = load <2 x double>, <2 x double>* %249
%251 = getelementptr inbounds double, double* %248, i64 2
%252 = bitcast double* %251 to <2 x double>*
%253 = load <2 x double>, <2 x double>* %252
%254 = getelementptr inbounds double, double* %191, i64 %247
%255 = bitcast double* %254 to <2 x double>*
%256 = load <2 x double>, <2 x double>* %255
%257 = getelementptr inbounds double, double* %254, i64 2
%258 = bitcast double* %257 to <2 x double>*
%259 = load <2 x double>, <2 x double>* %258
%260 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %201, <2 x double> %256, <2 x double> %250)
%261 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %203, <2 x double> %259, <2 x double> %253)
%262 = bitcast double* %248 to <2 x double>*
store <2 x double> %260, <2 x double>* %262
%263 = bitcast double* %251 to <2 x double>*
store <2 x double> %261, <2 x double>* %263
br label %264
264: ; preds = %244, %246
br i1 %59, label %293, label %265
265: ; preds = %193, %190, %264
%266 = phi i64 [ 1, %193 ], [ 1, %190 ], [ %54, %264 ]
%267 = xor i64 %266, -1
br i1 %61, label %268, label %275
268: ; preds = %265
%269 = getelementptr inbounds double, double* %3, i64 %266
%270 = load double, double* %269
%271 = getelementptr inbounds double, double* %191, i64 %266
%272 = load double, double* %271
%273 = tail call double @llvm.fmuladd.f64(double %192, double %272, double %270)
store double %273, double* %269
%274 = add nuw nsw i64 %266, 1
br label %275
275: ; preds = %268, %265
%276 = phi i64 [ %266, %265 ], [ %274, %268 ]
%277 = icmp eq i64 %267, %62
br i1 %277, label %293, label %278
278: ; preds = %275, %278
%279 = phi i64 [ %291, %278 ], [ %276, %275 ]
%280 = getelementptr inbounds double, double* %3, i64 %279
%281 = load double, double* %280
%282 = getelementptr inbounds double, double* %191, i64 %279
%283 = load double, double* %282
%284 = tail call double @llvm.fmuladd.f64(double %192, double %283, double %281)
store double %284, double* %280
%285 = add nuw nsw i64 %279, 1
%286 = getelementptr inbounds double, double* %3, i64 %285
%287 = load double, double* %286
%288 = getelementptr inbounds double, double* %191, i64 %285
%289 = load double, double* %288
%290 = tail call double @llvm.fmuladd.f64(double %192, double %289, double %287)
store double %290, double* %286
%291 = add nuw nsw i64 %279, 2
%292 = icmp eq i64 %291, %45
br i1 %292, label %293, label %278
293: ; preds = %275, %278, %264, %181
%294 = add nuw i64 %182, 1
%295 = trunc i64 %294 to i32
%296 = sitofp i32 %295 to double
%297 = load double*, double** %2
%298 = load double, double* %297
%299 = fcmp ult double %298, %296
br i1 %299, label %300, label %181
300: ; preds = %293, %38
ret double %6
}