void computeViterbiPath(int N, int S, double *pi, double *A, double *logdens,
                        double *indBestPath) {
  int n, s, s_;
  double tmp;
  double *pathLogLikelihood;
  int *indexAntecedent;
  indexAntecedent = (int *)malloc(N * S * sizeof(int));
  pathLogLikelihood = (double *)malloc(N * S * sizeof(double));
  for (s = 0; s < S; s++) {
    pathLogLikelihood[s + 0 * S] = logdens[s + 0 * S] + log(pi[s]);
    indexAntecedent[s + 0 * S] = 0;
  }
  for (n = 1; n < N; n++) {
    for (s = 0; s < S; s++) {
      pathLogLikelihood[s + n * S] =
          pathLogLikelihood[0 + (n - 1) * S] + log(A[s + 0 * S]);
      indexAntecedent[s + n * S] = 0;
      for (s_ = 1; s_ < S; s_++) {
        tmp = pathLogLikelihood[s_ + (n - 1) * S] + log(A[s + s_ * S]);
        if (tmp > pathLogLikelihood[s + n * S]) {
          pathLogLikelihood[s + n * S] = tmp;
          indexAntecedent[s + n * S] = s_;
        }
      }
      pathLogLikelihood[s + n * S] =
          pathLogLikelihood[s + n * S] + logdens[s + n * S];
    }
  }
  maxind(&pathLogLikelihood[(N - 1) * S], S, &tmp, &indBestPath[N - 1]);
  for (n = N - 2; n > -1; n--) {
    indBestPath[n] = indexAntecedent[(n + 1) * S + (int)indBestPath[n + 1]];
  }
  free(pathLogLikelihood);
  free(indexAntecedent);
}


x86 assembly (clang, -O0):
<computeViterbiPath>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %rdx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
mov    -0x4(%rbp),%eax
imul   -0x8(%rbp),%eax
movslq %eax,%rdi
shl    $0x2,%rdi
call   1040 <malloc@plt>
mov    %rax,-0x50(%rbp)
mov    -0x4(%rbp),%eax
imul   -0x8(%rbp),%eax
movslq %eax,%rdi
shl    $0x3,%rdi
call   1040 <malloc@plt>
mov    %rax,-0x48(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    1211 <computeViterbiPath+0xd1>
mov    -0x20(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   $0x0,-0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1060 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x58(%rbp),%xmm0
addsd  %xmm1,%xmm0
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   $0x0,-0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x50(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   $0x0,-0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movl   $0x0,(%rax,%rcx,4)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1193 <computeViterbiPath+0x53>
movl   $0x1,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    13e3 <computeViterbiPath+0x2a3>
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    13d0 <computeViterbiPath+0x290>
mov    -0x48(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
imul   -0x8(%rbp),%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   $0x0,-0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1060 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x60(%rbp),%xmm0
addsd  %xmm1,%xmm0
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x50(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movl   $0x0,(%rax,%rcx,4)
movl   $0x1,-0x34(%rbp)
mov    -0x34(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    137a <computeViterbiPath+0x23a>
mov    -0x48(%rbp),%rax
mov    -0x34(%rbp),%ecx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x34(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1060 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x68(%rbp),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm0
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
ucomisd (%rax,%rcx,8),%xmm0
jbe    1367 <computeViterbiPath+0x227>
movsd  -0x40(%rbp),%xmm0
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x34(%rbp),%edx
mov    -0x50(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%esi
imul   -0x8(%rbp),%esi
add    %esi,%ecx
movslq %ecx,%rcx
mov    %edx,(%rax,%rcx,4)
jmp    136c <computeViterbiPath+0x22c>
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    12b4 <computeViterbiPath+0x174>
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x20(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm0
mov    -0x48(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   -0x8(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    122b <computeViterbiPath+0xeb>
jmp    13d5 <computeViterbiPath+0x295>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1218 <computeViterbiPath+0xd8>
mov    -0x48(%rbp),%rdi
mov    -0x4(%rbp),%eax
sub    $0x1,%eax
imul   -0x8(%rbp),%eax
cltq
shl    $0x3,%rax
add    %rax,%rdi
mov    -0x8(%rbp),%esi
mov    -0x28(%rbp),%rcx
mov    -0x4(%rbp),%eax
sub    $0x1,%eax
cltq
shl    $0x3,%rax
add    %rax,%rcx
lea    -0x40(%rbp),%rdx
mov    $0x0,%al
call   1050 <maxind@plt>
mov    -0x4(%rbp),%eax
sub    $0x2,%eax
mov    %eax,-0x2c(%rbp)
cmpl   $0xffffffff,-0x2c(%rbp)
jle    1473 <computeViterbiPath+0x333>
mov    -0x50(%rbp),%rax
mov    -0x2c(%rbp),%ecx
add    $0x1,%ecx
imul   -0x8(%rbp),%ecx
mov    -0x28(%rbp),%rdx
mov    -0x2c(%rbp),%esi
add    $0x1,%esi
movslq %esi,%rsi
cvttsd2si (%rdx,%rsi,8),%edx
add    %edx,%ecx
movslq %ecx,%rcx
cvtsi2sdl (%rax,%rcx,4),%xmm0
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x2c(%rbp)
jmp    1424 <computeViterbiPath+0x2e4>
mov    -0x48(%rbp),%rdi
call   1030 <free@plt>
mov    -0x50(%rbp),%rdi
call   1030 <free@plt>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<computeViterbiPath>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x98,%rsp
mov    %r9,0x20(%rsp)
mov    %r8,%rbp
mov    %rcx,0x28(%rsp)
mov    %rdx,%r14
mov    %esi,%r13d
mov    %edi,%r15d
mov    %esi,%eax
imul   %edi,%eax
movslq %eax,%rbx
lea    0x0(,%rbx,4),%rdi
call   1050 <malloc@plt>
mov    %rax,%r12
shl    $0x3,%rbx
mov    %rbx,%rdi
call   1050 <malloc@plt>
mov    %r13d,%ecx
mov    %rcx,0x18(%rsp)
test   %r13d,%r13d
mov    %rax,0x8(%rsp)
jle    1202 <computeViterbiPath+0xb2>
mov    0x18(%rsp),%rax
lea    0x0(,%rax,4),%rdx
xor    %ebx,%ebx
mov    %r12,%rdi
xor    %esi,%esi
call   1040 <memset@plt>
cs nopw 0x0(%rax,%rax,1)
movsd  0x0(%rbp,%rbx,8),%xmm0
movsd  %xmm0,0x10(%rsp)
movsd  (%r14,%rbx,8),%xmm0
call   1070 <log@plt>
mov    0x8(%rsp),%rax
addsd  0x10(%rsp),%xmm0
movsd  %xmm0,(%rax,%rbx,8)
add    $0x1,%rbx
cmp    %rbx,0x18(%rsp)
jne    11d0 <computeViterbiPath+0x80>
cmp    $0x2,%r15d
jl     13a2 <computeViterbiPath+0x252>
movslq %r13d,%rdx
mov    %r15,0x40(%rsp)
mov    %r15d,%ecx
mov    %rcx,0x58(%rsp)
mov    0x28(%rsp),%rcx
lea    (%rcx,%rdx,8),%rcx
mov    %rcx,0x48(%rsp)
mov    %rdx,0x50(%rsp)
lea    0x0(,%rdx,8),%r14
mov    $0x1,%edx
mov    %rax,%rbx
mov    %rbp,0x68(%rsp)
mov    %r13,0x70(%rsp)
jmp    1267 <computeViterbiPath+0x117>
nopl   0x0(%rax,%rax,1)
mov    0x60(%rsp),%rdx
add    $0x1,%rdx
add    %r14,%rbx
cmp    0x58(%rsp),%rdx
je     13de <computeViterbiPath+0x28e>
test   %r13d,%r13d
mov    %rdx,0x60(%rsp)
jle    1250 <computeViterbiPath+0x100>
lea    -0x1(%rdx),%rsi
mov    0x50(%rsp),%rcx
imul   %rcx,%rsi
mov    %rsi,0x80(%rsp)
imul   %rcx,%rdx
mov    %rdx,0x78(%rsp)
mov    0x48(%rsp),%rcx
mov    %rcx,0x30(%rsp)
xor    %ebp,%ebp
jmp    12d0 <computeViterbiPath+0x180>
nopl   (%rax)
mov    0x68(%rsp),%rcx
addsd  (%rcx,%rbp,8),%xmm0
movsd  %xmm0,(%rax,%rbp,8)
mov    0x90(%rsp),%rbp
add    $0x1,%rbp
addq   $0x8,0x30(%rsp)
cmp    0x18(%rsp),%rbp
mov    %r15,%r12
mov    0x70(%rsp),%r13
je     1250 <computeViterbiPath+0x100>
movsd  %xmm1,0x10(%rsp)
mov    0x80(%rsp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,0x88(%rsp)
mov    0x28(%rsp),%rax
movsd  (%rax,%rbp,8),%xmm0
call   1070 <log@plt>
movsd  0x10(%rsp),%xmm1
mov    0x8(%rsp),%rax
mov    0x78(%rsp),%rcx
mov    %rbp,0x90(%rsp)
add    %rcx,%rbp
addsd  0x88(%rsp),%xmm0
movsd  %xmm0,(%rax,%rbp,8)
mov    %r12,%r15
movl   $0x0,(%r12,%rbp,4)
cmp    $0x2,%r13d
jl     12a0 <computeViterbiPath+0x150>
mov    $0x1,%r12d
mov    0x30(%rsp),%r13
jmp    1362 <computeViterbiPath+0x212>
cs nopw 0x0(%rax,%rax,1)
add    $0x1,%r12
add    %r14,%r13
cmp    %r12,0x18(%rsp)
je     12a0 <computeViterbiPath+0x150>
movsd  (%rbx,%r12,8),%xmm0
movsd  %xmm0,0x10(%rsp)
movsd  0x0(%r13),%xmm0
call   1070 <log@plt>
mov    0x8(%rsp),%rax
movapd %xmm0,%xmm1
addsd  0x10(%rsp),%xmm1
movsd  (%rax,%rbp,8),%xmm0
ucomisd %xmm0,%xmm1
jbe    1350 <computeViterbiPath+0x200>
movsd  %xmm1,(%rax,%rbp,8)
mov    %r12d,(%r15,%rbp,4)
movapd %xmm1,%xmm0
jmp    1350 <computeViterbiPath+0x200>
lea    -0x1(%r15),%eax
imul   %r13d,%eax
cltq
mov    0x8(%rsp),%rcx
lea    (%rcx,%rax,8),%rdi
movslq %r15d,%rax
mov    0x20(%rsp),%rcx
lea    (%rcx,%rax,8),%rcx
add    $0xfffffffffffffff8,%rcx
lea    0x38(%rsp),%rdx
mov    %r13d,%esi
xor    %eax,%eax
call   1060 <maxind@plt>
mov    0x8(%rsp),%rdi
jmp    14bc <computeViterbiPath+0x36c>
movsd  %xmm1,0x38(%rsp)
mov    0x40(%rsp),%rbx
lea    -0x1(%rbx),%r14d
imul   %r13d,%r14d
movslq %r14d,%rax
mov    0x8(%rsp),%rcx
lea    (%rcx,%rax,8),%rdi
movslq %ebx,%rax
mov    0x20(%rsp),%rbp
lea    -0x8(,%rax,8),%rcx
ff
add    %rbp,%rcx
lea    0x38(%rsp),%rdx
mov    %r13d,%esi
xor    %eax,%eax
call   1060 <maxind@plt>
mov    0x8(%rsp),%rdi
cmp    $0x2,%ebx
jl     14bc <computeViterbiPath+0x36c>
add    $0xfffffffe,%ebx
mov    %rbx,%rsi
test   $0x1,%bl
jne    1457 <computeViterbiPath+0x307>
cvttsd2si 0x8(%rbp,%rbx,8),%eax
add    %eax,%r14d
movslq %r14d,%rax
xorps  %xmm0,%xmm0
cvtsi2sdl (%r12,%rax,4),%xmm0
movsd  %xmm0,0x0(%rbp,%rbx,8)
lea    -0x1(%rbx),%rsi
test   %rbx,%rbx
je     14bc <computeViterbiPath+0x36c>
lea    0x1(%rsi),%eax
imul   %r13d,%eax
lea    0x0(%r13,%r13,1),%ecx
mov    %rsi,%rdx
add    $0x1,%rdx
imul   %esi,%r13d
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
cvttsd2si 0x0(%rbp,%rdx,8),%esi
add    %eax,%esi
movslq %esi,%rsi
mov    (%r12,%rsi,4),%esi
xorps  %xmm0,%xmm0
cvtsi2sd %esi,%xmm0
movsd  %xmm0,-0x8(%rbp,%rdx,8)
add    %r13d,%esi
movslq %esi,%rsi
xorps  %xmm0,%xmm0
cvtsi2sdl (%r12,%rsi,4),%xmm0
movsd  %xmm0,-0x10(%rbp,%rdx,8)
sub    %ecx,%eax
sub    %ecx,%r13d
add    $0xfffffffffffffffe,%rdx
jne    1480 <computeViterbiPath+0x330>
call   1030 <free@plt>
mov    %r12,%rdi
call   1030 <free@plt>
add    $0x98,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @computeViterbiPath(i32 %0, i32 %1, double* %2, double* %3, double* %4, double* %5) {
%7 = alloca i32
%8 = alloca i32
%9 = alloca double*
%10 = alloca double*
%11 = alloca double*
%12 = alloca double*
%13 = alloca i32
%14 = alloca i32
%15 = alloca i32
%16 = alloca double
%17 = alloca double*
%18 = alloca i32*
store i32 %0, i32* %7
store i32 %1, i32* %8
store double* %2, double** %9
store double* %3, double** %10
store double* %4, double** %11
store double* %5, double** %12
%19 = load i32, i32* %7
%20 = load i32, i32* %8
%21 = mul nsw i32 %19, %20
%22 = sext i32 %21 to i64
%23 = mul i64 %22, 4
%24 = call i8* @malloc(i64 %23)
%25 = bitcast i8* %24 to i32*
store i32* %25, i32** %18
%26 = load i32, i32* %7
%27 = load i32, i32* %8
%28 = mul nsw i32 %26, %27
%29 = sext i32 %28 to i64
%30 = mul i64 %29, 8
%31 = call i8* @malloc(i64 %30)
%32 = bitcast i8* %31 to double*
store double* %32, double** %17
store i32 0, i32* %14
br label %33
33: ; preds = %67, %6
%34 = load i32, i32* %14
%35 = load i32, i32* %8
%36 = icmp slt i32 %34, %35
br i1 %36, label %37, label %70
37: ; preds = %33
%38 = load double*, double** %11
%39 = load i32, i32* %14
%40 = load i32, i32* %8
%41 = mul nsw i32 0, %40
%42 = add nsw i32 %39, %41
%43 = sext i32 %42 to i64
%44 = getelementptr inbounds double, double* %38, i64 %43
%45 = load double, double* %44
%46 = load double*, double** %9
%47 = load i32, i32* %14
%48 = sext i32 %47 to i64
%49 = getelementptr inbounds double, double* %46, i64 %48
%50 = load double, double* %49
%51 = call double @log(double %50)
%52 = fadd double %45, %51
%53 = load double*, double** %17
%54 = load i32, i32* %14
%55 = load i32, i32* %8
%56 = mul nsw i32 0, %55
%57 = add nsw i32 %54, %56
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds double, double* %53, i64 %58
store double %52, double* %59
%60 = load i32*, i32** %18
%61 = load i32, i32* %14
%62 = load i32, i32* %8
%63 = mul nsw i32 0, %62
%64 = add nsw i32 %61, %63
%65 = sext i32 %64 to i64
%66 = getelementptr inbounds i32, i32* %60, i64 %65
store i32 0, i32* %66
br label %67
67: ; preds = %37
%68 = load i32, i32* %14
%69 = add nsw i32 %68, 1
store i32 %69, i32* %14
br label %33
70: ; preds = %33
store i32 1, i32* %13
br label %71
71: ; preds = %208, %70
%72 = load i32, i32* %13
%73 = load i32, i32* %7
%74 = icmp slt i32 %72, %73
br i1 %74, label %75, label %211
75: ; preds = %71
store i32 0, i32* %14
br label %76
76: ; preds = %204, %75
%77 = load i32, i32* %14
%78 = load i32, i32* %8
%79 = icmp slt i32 %77, %78
br i1 %79, label %80, label %207
80: ; preds = %76
%81 = load double*, double** %17
%82 = load i32, i32* %13
%83 = sub nsw i32 %82, 1
%84 = load i32, i32* %8
%85 = mul nsw i32 %83, %84
%86 = add nsw i32 0, %85
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds double, double* %81, i64 %87
%89 = load double, double* %88
%90 = load double*, double** %10
%91 = load i32, i32* %14
%92 = load i32, i32* %8
%93 = mul nsw i32 0, %92
%94 = add nsw i32 %91, %93
%95 = sext i32 %94 to i64
%96 = getelementptr inbounds double, double* %90, i64 %95
%97 = load double, double* %96
%98 = call double @log(double %97)
%99 = fadd double %89, %98
%100 = load double*, double** %17
%101 = load i32, i32* %14
%102 = load i32, i32* %13
%103 = load i32, i32* %8
%104 = mul nsw i32 %102, %103
%105 = add nsw i32 %101, %104
%106 = sext i32 %105 to i64
%107 = getelementptr inbounds double, double* %100, i64 %106
store double %99, double* %107
%108 = load i32*, i32** %18
%109 = load i32, i32* %14
%110 = load i32, i32* %13
%111 = load i32, i32* %8
%112 = mul nsw i32 %110, %111
%113 = add nsw i32 %109, %112
%114 = sext i32 %113 to i64
%115 = getelementptr inbounds i32, i32* %108, i64 %114
store i32 0, i32* %115
store i32 1, i32* %15
br label %116
116: ; preds = %173, %80
%117 = load i32, i32* %15
%118 = load i32, i32* %8
%119 = icmp slt i32 %117, %118
br i1 %119, label %120, label %176
120: ; preds = %116
%121 = load double*, double** %17
%122 = load i32, i32* %15
%123 = load i32, i32* %13
%124 = sub nsw i32 %123, 1
%125 = load i32, i32* %8
%126 = mul nsw i32 %124, %125
%127 = add nsw i32 %122, %126
%128 = sext i32 %127 to i64
%129 = getelementptr inbounds double, double* %121, i64 %128
%130 = load double, double* %129
%131 = load double*, double** %10
%132 = load i32, i32* %14
%133 = load i32, i32* %15
%134 = load i32, i32* %8
%135 = mul nsw i32 %133, %134
%136 = add nsw i32 %132, %135
%137 = sext i32 %136 to i64
%138 = getelementptr inbounds double, double* %131, i64 %137
%139 = load double, double* %138
%140 = call double @log(double %139)
%141 = fadd double %130, %140
store double %141, double* %16
%142 = load double, double* %16
%143 = load double*, double** %17
%144 = load i32, i32* %14
%145 = load i32, i32* %13
%146 = load i32, i32* %8
%147 = mul nsw i32 %145, %146
%148 = add nsw i32 %144, %147
%149 = sext i32 %148 to i64
%150 = getelementptr inbounds double, double* %143, i64 %149
%151 = load double, double* %150
%152 = fcmp ogt double %142, %151
br i1 %152, label %153, label %172
153: ; preds = %120
%154 = load double, double* %16
%155 = load double*, double** %17
%156 = load i32, i32* %14
%157 = load i32, i32* %13
%158 = load i32, i32* %8
%159 = mul nsw i32 %157, %158
%160 = add nsw i32 %156, %159
%161 = sext i32 %160 to i64
%162 = getelementptr inbounds double, double* %155, i64 %161
store double %154, double* %162
%163 = load i32, i32* %15
%164 = load i32*, i32** %18
%165 = load i32, i32* %14
%166 = load i32, i32* %13
%167 = load i32, i32* %8
%168 = mul nsw i32 %166, %167
%169 = add nsw i32 %165, %168
%170 = sext i32 %169 to i64
%171 = getelementptr inbounds i32, i32* %164, i64 %170
store i32 %163, i32* %171
br label %172
172: ; preds = %153, %120
br label %173
173: ; preds = %172
%174 = load i32, i32* %15
%175 = add nsw i32 %174, 1
store i32 %175, i32* %15
br label %116
176: ; preds = %116
%177 = load double*, double** %17
%178 = load i32, i32* %14
%179 = load i32, i32* %13
%180 = load i32, i32* %8
%181 = mul nsw i32 %179, %180
%182 = add nsw i32 %178, %181
%183 = sext i32 %182 to i64
%184 = getelementptr inbounds double, double* %177, i64 %183
%185 = load double, double* %184
%186 = load double*, double** %11
%187 = load i32, i32* %14
%188 = load i32, i32* %13
%189 = load i32, i32* %8
%190 = mul nsw i32 %188, %189
%191 = add nsw i32 %187, %190
%192 = sext i32 %191 to i64
%193 = getelementptr inbounds double, double* %186, i64 %192
%194 = load double, double* %193
%195 = fadd double %185, %194
%196 = load double*, double** %17
%197 = load i32, i32* %14
%198 = load i32, i32* %13
%199 = load i32, i32* %8
%200 = mul nsw i32 %198, %199
%201 = add nsw i32 %197, %200
%202 = sext i32 %201 to i64
%203 = getelementptr inbounds double, double* %196, i64 %202
store double %195, double* %203
br label %204
204: ; preds = %176
%205 = load i32, i32* %14
%206 = add nsw i32 %205, 1
store i32 %206, i32* %14
br label %76
207: ; preds = %76
br label %208
208: ; preds = %207
%209 = load i32, i32* %13
%210 = add nsw i32 %209, 1
store i32 %210, i32* %13
br label %71
211: ; preds = %71
%212 = load double*, double** %17
%213 = load i32, i32* %7
%214 = sub nsw i32 %213, 1
%215 = load i32, i32* %8
%216 = mul nsw i32 %214, %215
%217 = sext i32 %216 to i64
%218 = getelementptr inbounds double, double* %212, i64 %217
%219 = load i32, i32* %8
%220 = load double*, double** %12
%221 = load i32, i32* %7
%222 = sub nsw i32 %221, 1
%223 = sext i32 %222 to i64
%224 = getelementptr inbounds double, double* %220, i64 %223
%225 = call i32 (double*, i32, double*, double*, ...) bitcast (i32 (...)* @maxind to i32 (double*, i32, double*, double*, ...)*)(double* %218, i32 %219, double* %16, double* %224)
%226 = load i32, i32* %7
%227 = sub nsw i32 %226, 2
store i32 %227, i32* %13
br label %228
228: ; preds = %253, %211
%229 = load i32, i32* %13
%230 = icmp sgt i32 %229, -1
br i1 %230, label %231, label %256
231: ; preds = %228
%232 = load i32*, i32** %18
%233 = load i32, i32* %13
%234 = add nsw i32 %233, 1
%235 = load i32, i32* %8
%236 = mul nsw i32 %234, %235
%237 = load double*, double** %12
%238 = load i32, i32* %13
%239 = add nsw i32 %238, 1
%240 = sext i32 %239 to i64
%241 = getelementptr inbounds double, double* %237, i64 %240
%242 = load double, double* %241
%243 = fptosi double %242 to i32
%244 = add nsw i32 %236, %243
%245 = sext i32 %244 to i64
%246 = getelementptr inbounds i32, i32* %232, i64 %245
%247 = load i32, i32* %246
%248 = sitofp i32 %247 to double
%249 = load double*, double** %12
%250 = load i32, i32* %13
%251 = sext i32 %250 to i64
%252 = getelementptr inbounds double, double* %249, i64 %251
store double %248, double* %252
br label %253
253: ; preds = %231
%254 = load i32, i32* %13
%255 = add nsw i32 %254, -1
store i32 %255, i32* %13
br label %228
256: ; preds = %228
%257 = load double*, double** %17
%258 = bitcast double* %257 to i8*
%259 = load i32*, i32** %18
%260 = bitcast i32* %259 to i8*
ret void
}

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