#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 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;
  *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];
    }
  }
  for (k = 0; k < *K; k++) {
    a_Z_normalized[k] = exp(a_Z_normalized[k] - max_exp);
    *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    $0x40,%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>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    120d <e_step_with_stable_exp+0xfd>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
subsd  -0x40(%rbp),%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    11b3 <e_step_with_stable_exp+0xa3>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x8(%rbp),%rcx
cmp    (%rcx),%eax
jge    1253 <e_step_with_stable_exp+0x143>
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    1214 <e_step_with_stable_exp+0x104>
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<e_step_with_stable_exp>:
push   %r15
push   %r14
push   %r12
push   %rbx
push   %rax
mov    %rdx,%r14
mov    %rsi,%r12
mov    %rdi,%r15
movq   $0x0,(%rdx)
movq   $0x0,(%rcx)
movl   $0x0,(%r8)
movsd  (%rsi),%xmm0
mov    (%rdi),%eax
movapd %xmm0,%xmm2
cmp    $0x2,%eax
jl     11e6 <e_step_with_stable_exp+0xd6>
lea    -0x1(%rax),%rsi
lea    -0x2(%rax),%rdx
mov    %esi,%ecx
and    $0x3,%ecx
cmp    $0x3,%rdx
jae    1167 <e_step_with_stable_exp+0x57>
mov    $0x1,%edx
movapd %xmm0,%xmm1
jmp    11b9 <e_step_with_stable_exp+0xa9>
and    $0xfffffffffffffffc,%rsi
xor    %edx,%edx
movapd %xmm0,%xmm1
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsd  0x8(%r12,%rdx,8),%xmm2
maxsd  %xmm1,%xmm2
movsd  0x10(%r12,%rdx,8),%xmm1
maxsd  %xmm2,%xmm1
movsd  0x18(%r12,%rdx,8),%xmm2
maxsd  %xmm1,%xmm2
movsd  0x20(%r12,%rdx,8),%xmm1
maxsd  %xmm2,%xmm1
add    $0x4,%rdx
cmp    %rdx,%rsi
jne    1180 <e_step_with_stable_exp+0x70>
add    $0x1,%rdx
movapd %xmm1,%xmm2
test   %rcx,%rcx
je     11e6 <e_step_with_stable_exp+0xd6>
lea    (%r12,%rdx,8),%rdx
xor    %esi,%esi
nopl   0x0(%rax,%rax,1)
movsd  (%rdx,%rsi,8),%xmm2
maxsd  %xmm1,%xmm2
add    $0x1,%rsi
movapd %xmm2,%xmm1
cmp    %rsi,%rcx
jne    11d0 <e_step_with_stable_exp+0xc0>
test   %eax,%eax
jle    1353 <e_step_with_stable_exp+0x243>
movsd  %xmm2,(%rsp)
subsd  %xmm2,%xmm0
call   1030 <exp@plt>
movsd  %xmm0,(%r12)
addsd  (%r14),%xmm0
movsd  %xmm0,(%r14)
mov    (%r15),%ecx
cmp    $0x2,%ecx
jl     124c <e_step_with_stable_exp+0x13c>
mov    $0x1,%ebx
nopl   0x0(%rax)
movsd  (%r12,%rbx,8),%xmm0
subsd  (%rsp),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,(%r12,%rbx,8)
addsd  (%r14),%xmm0
movsd  %xmm0,(%r14)
add    $0x1,%rbx
movslq (%r15),%rcx
cmp    %rcx,%rbx
jl     1220 <e_step_with_stable_exp+0x110>
test   %ecx,%ecx
jle    1353 <e_step_with_stable_exp+0x243>
mov    %ecx,%eax
cmp    $0x1,%ecx
je     126d <e_step_with_stable_exp+0x15d>
lea    0x8(%r14),%rcx
cmp    %r12,%rcx
jbe    12d2 <e_step_with_stable_exp+0x1c2>
lea    (%r12,%rax,8),%rcx
cmp    %r14,%rcx
jbe    12d2 <e_step_with_stable_exp+0x1c2>
xor    %ecx,%ecx
mov    %rcx,%rdx
not    %rdx
test   $0x1,%al
je     128e <e_step_with_stable_exp+0x17e>
movsd  (%r12,%rcx,8),%xmm0
divsd  (%r14),%xmm0
movsd  %xmm0,(%r12,%rcx,8)
or     $0x1,%rcx
add    %rax,%rdx
je     1353 <e_step_with_stable_exp+0x243>
nopw   0x0(%rax,%rax,1)
movsd  (%r12,%rcx,8),%xmm0
divsd  (%r14),%xmm0
movsd  0x8(%r12,%rcx,8),%xmm1
movsd  %xmm0,(%r12,%rcx,8)
divsd  (%r14),%xmm1
movsd  %xmm1,0x8(%r12,%rcx,8)
add    $0x2,%rcx
cmp    %rcx,%rax
jne    12a0 <e_step_with_stable_exp+0x190>
jmp    1353 <e_step_with_stable_exp+0x243>
mov    %eax,%ecx
and    $0xfffffffe,%ecx
lea    -0x2(%rcx),%rsi
mov    %rsi,%rdx
shr    %rdx
add    $0x1,%rdx
test   %rsi,%rsi
je     135f <e_step_with_stable_exp+0x24f>
mov    %rdx,%rdi
and    $0xfffffffffffffffe,%rdi
movsd  (%r14),%xmm0
unpcklpd %xmm0,%xmm0
xor    %esi,%esi
nopl   0x0(%rax)
movupd (%r12,%rsi,8),%xmm1
movupd 0x10(%r12,%rsi,8),%xmm2
divpd  %xmm0,%xmm1
movupd %xmm1,(%r12,%rsi,8)
divpd  %xmm0,%xmm2
movupd %xmm2,0x10(%r12,%rsi,8)
add    $0x4,%rsi
add    $0xfffffffffffffffe,%rdi
jne    1300 <e_step_with_stable_exp+0x1f0>
test   $0x1,%dl
je     134a <e_step_with_stable_exp+0x23a>
movupd (%r12,%rsi,8),%xmm0
movsd  (%r14),%xmm1
unpcklpd %xmm1,%xmm1
divpd  %xmm1,%xmm0
movupd %xmm0,(%r12,%rsi,8)
cmp    %rax,%rcx
jne    126f <e_step_with_stable_exp+0x15f>
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret
xor    %esi,%esi
test   $0x1,%dl
jne    1331 <e_step_with_stable_exp+0x221>
jmp    134a <e_step_with_stable_exp+0x23a>

LLVM IR (-O0):
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
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
%14 = load double*, double** %8
store double 0.000000e+00, double* %14
%15 = load double*, double** %9
store double 0.000000e+00, double* %15
%16 = load i32*, i32** %10
store i32 0, i32* %16
%17 = load double*, double** %7
%18 = getelementptr inbounds double, double* %17, i64 0
%19 = load double, double* %18
store double %19, double* %13
store i32 1, i32* %11
br label %20
20: ; preds = %40, %5
%21 = load i32, i32* %11
%22 = load i32*, i32** %6
%23 = load i32, i32* %22
%24 = icmp slt i32 %21, %23
br i1 %24, label %25, label %43
25: ; preds = %20
%26 = load double*, double** %7
%27 = load i32, i32* %11
%28 = sext i32 %27 to i64
%29 = getelementptr inbounds double, double* %26, i64 %28
%30 = load double, double* %29
%31 = load double, double* %13
%32 = fcmp ogt double %30, %31
br i1 %32, label %33, label %39
33: ; preds = %25
%34 = load double*, double** %7
%35 = load i32, i32* %11
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds double, double* %34, i64 %36
%38 = load double, double* %37
store double %38, double* %13
br label %39
39: ; preds = %33, %25
br label %40
40: ; preds = %39
%41 = load i32, i32* %11
%42 = add nsw i32 %41, 1
store i32 %42, i32* %11
br label %20
43: ; preds = %20
store i32 0, i32* %11
br label %44
44: ; preds = %70, %43
%45 = load i32, i32* %11
%46 = load i32*, i32** %6
%47 = load i32, i32* %46
%48 = icmp slt i32 %45, %47
br i1 %48, label %49, label %73
49: ; preds = %44
%50 = load double*, double** %7
%51 = load i32, i32* %11
%52 = sext i32 %51 to i64
%53 = getelementptr inbounds double, double* %50, i64 %52
%54 = load double, double* %53
%55 = load double, double* %13
%56 = fsub double %54, %55
%57 = call double @exp(double %56)
%58 = load double*, double** %7
%59 = load i32, i32* %11
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds double, double* %58, i64 %60
store double %57, double* %61
%62 = load double*, double** %7
%63 = load i32, i32* %11
%64 = sext i32 %63 to i64
%65 = getelementptr inbounds double, double* %62, i64 %64
%66 = load double, double* %65
%67 = load double*, double** %8
%68 = load double, double* %67
%69 = fadd double %68, %66
store double %69, double* %67
br label %70
70: ; preds = %49
%71 = load i32, i32* %11
%72 = add nsw i32 %71, 1
store i32 %72, i32* %11
br label %44
73: ; preds = %44
store i32 0, i32* %11
br label %74
74: ; preds = %92, %73
%75 = load i32, i32* %11
%76 = load i32*, i32** %6
%77 = load i32, i32* %76
%78 = icmp slt i32 %75, %77
br i1 %78, label %79, label %95
79: ; preds = %74
%80 = load double*, double** %7
%81 = load i32, i32* %11
%82 = sext i32 %81 to i64
%83 = getelementptr inbounds double, double* %80, i64 %82
%84 = load double, double* %83
%85 = load double*, double** %8
%86 = load double, double* %85
%87 = fdiv double %84, %86
%88 = load double*, double** %7
%89 = load i32, i32* %11
%90 = sext i32 %89 to i64
%91 = getelementptr inbounds double, double* %88, i64 %90
store double %87, double* %91
br label %92
92: ; preds = %79
%93 = load i32, i32* %11
%94 = add nsw i32 %93, 1
store i32 %94, i32* %11
br label %74
95: ; preds = %74
ret void
}

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