#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 HUGE_VAL;
double exp(double);
void e_step_with_stable_exp(int *K, double *a_Z_normalized, double *total_sum,
                            double *scale_exp, int *flag_out_range) {
  int k;
  double tmp_exp, max_exp, tmp_exp_K, K_double;
  *total_sum = 0.0;
  *scale_exp = 0.0;
  *flag_out_range = 0;
  max_exp = a_Z_normalized[0];
  for (k = 1; k < *K; k++) {
    if (a_Z_normalized[k] > max_exp) {
      max_exp = a_Z_normalized[k];
    }
  }
  tmp_exp = exp(max_exp);
  K_double = (double)*K;
  tmp_exp_K = tmp_exp * K_double;
  if (tmp_exp == HUGE_VAL || tmp_exp == 0.0 || tmp_exp_K == HUGE_VAL) {
    *flag_out_range = 1;
    *scale_exp = (tmp_exp == HUGE_VAL) ? max_exp : -max_exp;
    do {
      *scale_exp *= 0.5;
      tmp_exp = exp(*scale_exp);
      tmp_exp_K = tmp_exp * K_double;
    } while (tmp_exp == HUGE_VAL || tmp_exp_K == HUGE_VAL);
    *scale_exp = max_exp - *scale_exp;
  }
  if (*flag_out_range) {
    for (k = 0; k < *K; k++) {
      a_Z_normalized[k] -= *scale_exp;
    }
  }
  *total_sum = 0.0;
  for (k = 0; k < *K; k++) {
    a_Z_normalized[k] = exp(a_Z_normalized[k]);
    *total_sum += a_Z_normalized[k];
  }
  for (k = 0; k < *K; k++) {
    a_Z_normalized[k] = a_Z_normalized[k] / *total_sum;
  }
}


x86 assembly (clang, -O0):
<e_step_with_stable_exp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
mov    -0x28(%rbp),%rax
movl   $0x0,(%rax)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x40(%rbp)
movl   $0x1,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    11ac <e_step_with_stable_exp+0x9c>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
ucomisd -0x40(%rbp),%xmm0
jbe    1199 <e_step_with_stable_exp+0x89>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x40(%rbp)
jmp    119e <e_step_with_stable_exp+0x8e>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1160 <e_step_with_stable_exp+0x50>
movsd  -0x40(%rbp),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
cvtsi2sdl (%rax),%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x38(%rbp),%xmm0
mulsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x38(%rbp),%xmm0
mov    0x2e05(%rip),%rax
ucomisd (%rax),%xmm0
jne    11f8 <e_step_with_stable_exp+0xe8>
jp     11f8 <e_step_with_stable_exp+0xe8>
jmp    1231 <e_step_with_stable_exp+0x121>
movsd  -0x38(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1215 <e_step_with_stable_exp+0x105>
jp     1215 <e_step_with_stable_exp+0x105>
jmp    1231 <e_step_with_stable_exp+0x121>
movsd  -0x48(%rbp),%xmm0
mov    0x2dc7(%rip),%rax
ucomisd (%rax),%xmm0
jne    132a <e_step_with_stable_exp+0x21a>
jp     132a <e_step_with_stable_exp+0x21a>
mov    -0x28(%rbp),%rax
movl   $0x1,(%rax)
movsd  -0x38(%rbp),%xmm0
mov    0x2da1(%rip),%rax
ucomisd (%rax),%xmm0
jne    1266 <e_step_with_stable_exp+0x156>
jp     1266 <e_step_with_stable_exp+0x156>
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
jmp    1287 <e_step_with_stable_exp+0x177>
movsd  -0x40(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x58(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  0xd60(%rip),%xmm0
mulsd  (%rax),%xmm0
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,-0x38(%rbp)
movsd  -0x38(%rbp),%xmm0
mulsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x38(%rbp),%xmm0
mov    $0x1,%al
mov    0x2d11(%rip),%rcx
ucomisd (%rcx),%xmm0
mov    %al,-0x59(%rbp)
jne    12ef <e_step_with_stable_exp+0x1df>
jp     12ef <e_step_with_stable_exp+0x1df>
jmp    130a <e_step_with_stable_exp+0x1fa>
movsd  -0x48(%rbp),%xmm0
mov    0x2ced(%rip),%rax
ucomisd (%rax),%xmm0
sete   %al
setnp  %cl
and    %cl,%al
mov    %al,-0x59(%rbp)
mov    -0x59(%rbp),%al
test   $0x1,%al
jne    1294 <e_step_with_stable_exp+0x184>
movsd  -0x40(%rbp),%xmm0
mov    -0x20(%rbp),%rax
subsd  (%rax),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x28(%rbp),%rax
cmpl   $0x0,(%rax)
je     137e <e_step_with_stable_exp+0x26e>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    1379 <e_step_with_stable_exp+0x269>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    133e <e_step_with_stable_exp+0x22e>
jmp    137e <e_step_with_stable_exp+0x26e>
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    13e5 <e_step_with_stable_exp+0x2d5>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1030 <exp@plt>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
addsd  (%rax),%xmm0
movsd  %xmm0,(%rax)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1390 <e_step_with_stable_exp+0x280>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    142b <e_step_with_stable_exp+0x31b>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
divsd  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    13ec <e_step_with_stable_exp+0x2dc>
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<e_step_with_stable_exp>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    %r8,%r13
mov    %rcx,%r12
mov    %rdx,%r14
mov    %rsi,%rbx
mov    %rdi,%r15
movq   $0x0,(%rdx)
movq   $0x0,(%rcx)
movl   $0x0,(%r8)
movsd  (%rsi),%xmm2
mov    (%rdi),%ecx
cmp    $0x2,%ecx
jl     1167 <e_step_with_stable_exp+0x57>
lea    -0x1(%rcx),%rdx
add    $0xfffffffffffffffe,%rcx
mov    %edx,%eax
and    $0x3,%eax
cmp    $0x3,%rcx
jae    116d <e_step_with_stable_exp+0x5d>
mov    $0x1,%ecx
jmp    11b5 <e_step_with_stable_exp+0xa5>
movapd %xmm2,%xmm0
jmp    11e6 <e_step_with_stable_exp+0xd6>
and    $0xfffffffffffffffc,%rdx
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movsd  0x8(%rbx,%rcx,8),%xmm1
maxsd  %xmm2,%xmm1
movsd  0x10(%rbx,%rcx,8),%xmm0
maxsd  %xmm1,%xmm0
movsd  0x18(%rbx,%rcx,8),%xmm1
maxsd  %xmm0,%xmm1
movsd  0x20(%rbx,%rcx,8),%xmm2
maxsd  %xmm1,%xmm2
add    $0x4,%rcx
cmp    %rcx,%rdx
jne    1180 <e_step_with_stable_exp+0x70>
add    $0x1,%rcx
movapd %xmm2,%xmm0
test   %rax,%rax
je     11e6 <e_step_with_stable_exp+0xd6>
lea    (%rbx,%rcx,8),%rcx
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movsd  (%rcx,%rdx,8),%xmm0
maxsd  %xmm2,%xmm0
add    $0x1,%rdx
movapd %xmm0,%xmm2
cmp    %rdx,%rax
jne    11d0 <e_step_with_stable_exp+0xc0>
movapd %xmm0,0x10(%rsp)
call   1030 <exp@plt>
xorps  %xmm1,%xmm1
cvtsi2sdl (%r15),%xmm1
movsd  %xmm1,0x8(%rsp)
mov    0x2de2(%rip),%rbp
movsd  0x0(%rbp),%xmm1
xorpd  %xmm2,%xmm2
ucomisd %xmm2,%xmm0
jne    1217 <e_step_with_stable_exp+0x107>
jnp    1231 <e_step_with_stable_exp+0x121>
ucomisd %xmm1,%xmm0
jne    121f <e_step_with_stable_exp+0x10f>
jnp    1231 <e_step_with_stable_exp+0x121>
movapd %xmm0,%xmm2
mulsd  0x8(%rsp),%xmm2
ucomisd %xmm1,%xmm2
jne    12a8 <e_step_with_stable_exp+0x198>
jp     12a8 <e_step_with_stable_exp+0x198>
movl   $0x1,0x0(%r13)
movapd 0xdbf(%rip),%xmm2
movapd 0x10(%rsp),%xmm3
xorpd  %xmm3,%xmm2
cmpeqsd %xmm1,%xmm0
movapd %xmm0,%xmm1
andpd  %xmm3,%xmm1
andnpd %xmm2,%xmm0
orpd   %xmm1,%xmm0
mulsd  0xda8(%rip),%xmm0
movsd  %xmm0,(%r12)
call   1030 <exp@plt>
movapd %xmm0,%xmm1
movsd  0x0(%rbp),%xmm2
ucomisd %xmm2,%xmm0
movsd  (%r12),%xmm0
jne    128a <e_step_with_stable_exp+0x17a>
jnp    1260 <e_step_with_stable_exp+0x150>
mulsd  0x8(%rsp),%xmm1
ucomisd %xmm2,%xmm1
jne    1298 <e_step_with_stable_exp+0x188>
jnp    1260 <e_step_with_stable_exp+0x150>
movapd 0x10(%rsp),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,(%r12)
cmpl   $0x0,0x0(%r13)
mov    (%r15),%eax
je     143f <e_step_with_stable_exp+0x32f>
test   %eax,%eax
jle    1384 <e_step_with_stable_exp+0x274>
cmp    $0x4,%eax
jb     12de <e_step_with_stable_exp+0x1ce>
lea    0x8(%r12),%rcx
cmp    %rbx,%rcx
jbe    1390 <e_step_with_stable_exp+0x280>
lea    (%rbx,%rax,8),%rcx
cmp    %r12,%rcx
jbe    1390 <e_step_with_stable_exp+0x280>
xor    %ecx,%ecx
mov    %rcx,%rdx
not    %rdx
add    %rax,%rdx
mov    %rax,%rsi
and    $0x3,%rsi
je     131a <e_step_with_stable_exp+0x20a>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsd  (%rbx,%rcx,8),%xmm0
subsd  (%r12),%xmm0
movsd  %xmm0,(%rbx,%rcx,8)
add    $0x1,%rcx
add    $0xffffffffffffffff,%rsi
jne    1300 <e_step_with_stable_exp+0x1f0>
cmp    $0x3,%rdx
jb     143f <e_step_with_stable_exp+0x32f>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movsd  (%rbx,%rcx,8),%xmm0
subsd  (%r12),%xmm0
movsd  0x8(%rbx,%rcx,8),%xmm1
movsd  %xmm0,(%rbx,%rcx,8)
subsd  (%r12),%xmm1
movsd  %xmm1,0x8(%rbx,%rcx,8)
movsd  0x10(%rbx,%rcx,8),%xmm0
subsd  (%r12),%xmm0
movsd  %xmm0,0x10(%rbx,%rcx,8)
movsd  0x18(%rbx,%rcx,8),%xmm0
subsd  (%r12),%xmm0
movsd  %xmm0,0x18(%rbx,%rcx,8)
add    $0x4,%rcx
cmp    %rcx,%rax
jne    1330 <e_step_with_stable_exp+0x220>
jmp    143f <e_step_with_stable_exp+0x32f>
movq   $0x0,(%r14)
jmp    15a9 <e_step_with_stable_exp+0x499>
mov    %eax,%ecx
and    $0xfffffffc,%ecx
lea    -0x4(%rcx),%rdx
mov    %rdx,%rsi
shr    $0x2,%rsi
add    $0x1,%rsi
test   %rdx,%rdx
je     151a <e_step_with_stable_exp+0x40a>
mov    %rsi,%rdi
and    $0xfffffffffffffffe,%rdi
movsd  (%r12),%xmm0
unpcklpd %xmm0,%xmm0
xor    %edx,%edx
movupd (%rbx,%rdx,8),%xmm1
movupd 0x10(%rbx,%rdx,8),%xmm2
movupd 0x20(%rbx,%rdx,8),%xmm3
movupd 0x30(%rbx,%rdx,8),%xmm4
subpd  %xmm0,%xmm1
subpd  %xmm0,%xmm2
movupd %xmm1,(%rbx,%rdx,8)
movupd %xmm2,0x10(%rbx,%rdx,8)
subpd  %xmm0,%xmm3
subpd  %xmm0,%xmm4
movupd %xmm3,0x20(%rbx,%rdx,8)
movupd %xmm4,0x30(%rbx,%rdx,8)
add    $0x8,%rdx
add    $0xfffffffffffffffe,%rdi
jne    13c0 <e_step_with_stable_exp+0x2b0>
test   $0x1,%sil
je     1436 <e_step_with_stable_exp+0x326>
movsd  (%r12),%xmm0
unpcklpd %xmm0,%xmm0
movupd (%rbx,%rdx,8),%xmm1
movupd 0x10(%rbx,%rdx,8),%xmm2
subpd  %xmm0,%xmm1
subpd  %xmm0,%xmm2
movupd %xmm1,(%rbx,%rdx,8)
movupd %xmm2,0x10(%rbx,%rdx,8)
cmp    %rax,%rcx
jne    12e0 <e_step_with_stable_exp+0x1d0>
movq   $0x0,(%r14)
test   %eax,%eax
jle    15a9 <e_step_with_stable_exp+0x499>
xor    %ebp,%ebp
movsd  (%rbx,%rbp,8),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,(%rbx,%rbp,8)
addsd  (%r14),%xmm0
movsd  %xmm0,(%r14)
add    $0x1,%rbp
movslq (%r15),%rax
cmp    %rax,%rbp
jl     1450 <e_step_with_stable_exp+0x340>
mov    %eax,%eax
test   %eax,%eax
jle    15a9 <e_step_with_stable_exp+0x499>
movsd  (%rbx),%xmm1
divsd  %xmm0,%xmm1
movsd  %xmm1,(%rbx)
cmp    $0x1,%eax
je     15a9 <e_step_with_stable_exp+0x499>
lea    -0x1(%rax),%rcx
mov    $0x1,%edx
cmp    $0x2,%rcx
jb     1559 <e_step_with_stable_exp+0x449>
cmp    %r14,%rbx
jae    14b9 <e_step_with_stable_exp+0x3a9>
lea    (%rbx,%rax,8),%rsi
cmp    %r14,%rsi
ja     1559 <e_step_with_stable_exp+0x449>
mov    %rcx,%rdx
and    $0xfffffffffffffffe,%rdx
lea    -0x2(%rdx),%rsi
mov    %rsi,%rbp
shr    %rbp
add    $0x1,%rbp
test   %rsi,%rsi
je     152b <e_step_with_stable_exp+0x41b>
mov    %rbp,%rsi
and    $0xfffffffffffffffe,%rsi
movsd  (%r14),%xmm0
unpcklpd %xmm0,%xmm0
mov    $0x1,%edi
nopl   0x0(%rax,%rax,1)
movupd (%rbx,%rdi,8),%xmm1
movupd 0x10(%rbx,%rdi,8),%xmm2
divpd  %xmm0,%xmm1
movupd %xmm1,(%rbx,%rdi,8)
divpd  %xmm0,%xmm2
movupd %xmm2,0x10(%rbx,%rdi,8)
add    $0x4,%rdi
add    $0xfffffffffffffffe,%rsi
jne    14f0 <e_step_with_stable_exp+0x3e0>
jmp    1530 <e_step_with_stable_exp+0x420>
xor    %edx,%edx
test   $0x1,%sil
jne    140e <e_step_with_stable_exp+0x2fe>
jmp    1436 <e_step_with_stable_exp+0x326>
mov    $0x1,%edi
test   $0x1,%bpl
je     154d <e_step_with_stable_exp+0x43d>
movsd  (%r14),%xmm0
unpcklpd %xmm0,%xmm0
movupd (%rbx,%rdi,8),%xmm1
divpd  %xmm0,%xmm1
movupd %xmm1,(%rbx,%rdi,8)
cmp    %rdx,%rcx
je     15a9 <e_step_with_stable_exp+0x499>
or     $0x1,%rcx
mov    %rcx,%rdx
mov    %rdx,%rcx
not    %rcx
test   $0x1,%al
jne    1576 <e_step_with_stable_exp+0x466>
movsd  (%rbx,%rdx,8),%xmm0
divsd  (%r14),%xmm0
movsd  %xmm0,(%rbx,%rdx,8)
add    $0x1,%rdx
add    %rax,%rcx
je     15a9 <e_step_with_stable_exp+0x499>
nopl   0x0(%rax,%rax,1)
movsd  (%rbx,%rdx,8),%xmm0
divsd  (%r14),%xmm0
movsd  0x8(%rbx,%rdx,8),%xmm1
movsd  %xmm0,(%rbx,%rdx,8)
divsd  (%r14),%xmm1
movsd  %xmm1,0x8(%rbx,%rdx,8)
add    $0x2,%rdx
cmp    %rdx,%rax
jne    1580 <e_step_with_stable_exp+0x470>
add    $0x28,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

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