void cal_tri_inv(double **S, double **S_inv, const int L) {
  int i, j, k;
  for (i = 0; i < L; i++) {
    S_inv[i][i] = 1.0 / S[i][i];
  }
  for (i = 1; i < L; i++)
    for (j = i - 1; j >= 0; j--)
      for (k = j; k < i; k++) {
        S_inv[i][j] = S_inv[i][j] - S[i][k] * S_inv[k][j] / S[i][i];
      }
}


x86 assembly (clang, -O0):
<cal_tri_inv>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1162 <cal_tri_inv+0x62>
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x18(%rbp),%rcx
movsd  0xec6(%rip),%xmm0
divsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x18(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1116 <cal_tri_inv+0x16>
movl   $0x1,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    123b <cal_tri_inv+0x13b>
mov    -0x18(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jl     1228 <cal_tri_inv+0x128>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x18(%rbp),%eax
jge    1215 <cal_tri_inv+0x115>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x1c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x1c(%rbp),%rcx
mulsd  (%rax,%rcx,8),%xmm1
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x18(%rbp),%rcx
divsd  (%rax,%rcx,8),%xmm1
subsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x1c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    118e <cal_tri_inv+0x8e>
jmp    121a <cal_tri_inv+0x11a>
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
jmp    117e <cal_tri_inv+0x7e>
jmp    122d <cal_tri_inv+0x12d>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1169 <cal_tri_inv+0x69>
pop    %rbp
ret

x86 assembly (clang, -O2):
<cal_tri_inv>:
push   %r15
push   %r14
push   %r12
push   %rbx
test   %edx,%edx
jle    127e <cal_tri_inv+0x17e>
mov    %edx,%r8d
cmp    $0x1,%edx
jne    111b <cal_tri_inv+0x1b>
xor    %ecx,%ecx
jmp    1169 <cal_tri_inv+0x69>
mov    %r8d,%eax
and    $0xfffffffe,%eax
xor    %ecx,%ecx
movsd  0xed5(%rip),%xmm0
nopl   0x0(%rax,%rax,1)
mov    (%rdi,%rcx,8),%rbx
movapd %xmm0,%xmm1
divsd  (%rbx,%rcx,8),%xmm1
mov    (%rsi,%rcx,8),%rbx
movsd  %xmm1,(%rbx,%rcx,8)
mov    0x8(%rdi,%rcx,8),%rbx
movapd %xmm0,%xmm1
divsd  0x8(%rbx,%rcx,8),%xmm1
mov    0x8(%rsi,%rcx,8),%rbx
movsd  %xmm1,0x8(%rbx,%rcx,8)
add    $0x2,%rcx
cmp    %rcx,%rax
jne    1130 <cal_tri_inv+0x30>
test   $0x1,%r8b
je     1189 <cal_tri_inv+0x89>
mov    (%rdi,%rcx,8),%rax
movsd  0xe85(%rip),%xmm0
divsd  (%rax,%rcx,8),%xmm0
mov    (%rsi,%rcx,8),%rax
movsd  %xmm0,(%rax,%rcx,8)
cmp    $0x2,%edx
jl     127e <cal_tri_inv+0x17e>
add    $0xffffffff,%edx
mov    $0x1,%r15d
xor    %r8d,%r8d
jmp    11b1 <cal_tri_inv+0xb1>
add    $0x1,%r15
add    $0x1,%r8
cmp    %rdx,%r8
je     127e <cal_tri_inv+0x17e>
xor    %r9d,%r9d
mov    %r15,%r12
mov    %r8,%r10
jmp    11ce <cal_tri_inv+0xce>
nopl   0x0(%rax)
add    $0xffffffffffffffff,%r10
add    $0x1,%r9
cmp    $0x2,%r11
jl     11a0 <cal_tri_inv+0xa0>
mov    %r12,%r11
add    $0xffffffffffffffff,%r12
cmp    %r15,%r11
jg     11c0 <cal_tri_inv+0xc0>
mov    (%rsi,%r15,8),%r14
mov    (%rdi,%r15,8),%rbx
movsd  (%r14,%r12,8),%xmm0
test   $0x1,%r9b
jne    1220 <cal_tri_inv+0x120>
movsd  (%rbx,%r10,8),%xmm1
mov    (%rsi,%r10,8),%rcx
mulsd  (%rcx,%r12,8),%xmm1
divsd  (%rbx,%r15,8),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,(%r14,%r12,8)
lea    0x1(%r10),%rcx
test   %r9,%r9
jne    1230 <cal_tri_inv+0x130>
jmp    11c0 <cal_tri_inv+0xc0>
nopl   0x0(%rax)
mov    %r10,%rcx
test   %r9,%r9
je     11c0 <cal_tri_inv+0xc0>
nopl   0x0(%rax,%rax,1)
movsd  (%rbx,%rcx,8),%xmm1
mov    (%rsi,%rcx,8),%rax
mulsd  (%rax,%r12,8),%xmm1
divsd  (%rbx,%r15,8),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,(%r14,%r12,8)
movsd  0x8(%rbx,%rcx,8),%xmm1
mov    0x8(%rsi,%rcx,8),%rax
mulsd  (%rax,%r12,8),%xmm1
divsd  (%rbx,%r15,8),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,(%r14,%r12,8)
add    $0x2,%rcx
cmp    %rcx,%r15
jne    1230 <cal_tri_inv+0x130>
jmp    11c0 <cal_tri_inv+0xc0>
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @cal_tri_inv(double** %0, double** %1, i32 %2) {
%4 = alloca double**
%5 = alloca double**
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
store double** %0, double*** %4
store double** %1, double*** %5
store i32 %2, i32* %6
store i32 0, i32* %7
br label %10
10: ; preds = %33, %3
%11 = load i32, i32* %7
%12 = load i32, i32* %6
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %36
14: ; preds = %10
%15 = load double**, double*** %4
%16 = load i32, i32* %7
%17 = sext i32 %16 to i64
%18 = getelementptr inbounds double*, double** %15, i64 %17
%19 = load double*, double** %18
%20 = load i32, i32* %7
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds double, double* %19, i64 %21
%23 = load double, double* %22
%24 = fdiv double 1.000000e+00, %23
%25 = load double**, double*** %5
%26 = load i32, i32* %7
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds double*, double** %25, i64 %27
%29 = load double*, double** %28
%30 = load i32, i32* %7
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds double, double* %29, i64 %31
store double %24, double* %32
br label %33
33: ; preds = %14
%34 = load i32, i32* %7
%35 = add nsw i32 %34, 1
store i32 %35, i32* %7
br label %10
36: ; preds = %10
store i32 1, i32* %7
br label %37
37: ; preds = %109, %36
%38 = load i32, i32* %7
%39 = load i32, i32* %6
%40 = icmp slt i32 %38, %39
br i1 %40, label %41, label %112
41: ; preds = %37
%42 = load i32, i32* %7
%43 = sub nsw i32 %42, 1
store i32 %43, i32* %8
br label %44
44: ; preds = %105, %41
%45 = load i32, i32* %8
%46 = icmp sge i32 %45, 0
br i1 %46, label %47, label %108
47: ; preds = %44
%48 = load i32, i32* %8
store i32 %48, i32* %9
br label %49
49: ; preds = %101, %47
%50 = load i32, i32* %9
%51 = load i32, i32* %7
%52 = icmp slt i32 %50, %51
br i1 %52, label %53, label %104
53: ; preds = %49
%54 = load double**, double*** %5
%55 = load i32, i32* %7
%56 = sext i32 %55 to i64
%57 = getelementptr inbounds double*, double** %54, i64 %56
%58 = load double*, double** %57
%59 = load i32, i32* %8
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds double, double* %58, i64 %60
%62 = load double, double* %61
%63 = load double**, double*** %4
%64 = load i32, i32* %7
%65 = sext i32 %64 to i64
%66 = getelementptr inbounds double*, double** %63, i64 %65
%67 = load double*, double** %66
%68 = load i32, i32* %9
%69 = sext i32 %68 to i64
%70 = getelementptr inbounds double, double* %67, i64 %69
%71 = load double, double* %70
%72 = load double**, double*** %5
%73 = load i32, i32* %9
%74 = sext i32 %73 to i64
%75 = getelementptr inbounds double*, double** %72, i64 %74
%76 = load double*, double** %75
%77 = load i32, i32* %8
%78 = sext i32 %77 to i64
%79 = getelementptr inbounds double, double* %76, i64 %78
%80 = load double, double* %79
%81 = fmul double %71, %80
%82 = load double**, double*** %4
%83 = load i32, i32* %7
%84 = sext i32 %83 to i64
%85 = getelementptr inbounds double*, double** %82, i64 %84
%86 = load double*, double** %85
%87 = load i32, i32* %7
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds double, double* %86, i64 %88
%90 = load double, double* %89
%91 = fdiv double %81, %90
%92 = fsub double %62, %91
%93 = load double**, double*** %5
%94 = load i32, i32* %7
%95 = sext i32 %94 to i64
%96 = getelementptr inbounds double*, double** %93, i64 %95
%97 = load double*, double** %96
%98 = load i32, i32* %8
%99 = sext i32 %98 to i64
%100 = getelementptr inbounds double, double* %97, i64 %99
store double %92, double* %100
br label %101
101: ; preds = %53
%102 = load i32, i32* %9
%103 = add nsw i32 %102, 1
store i32 %103, i32* %9
br label %49
104: ; preds = %49
br label %105
105: ; preds = %104
%106 = load i32, i32* %8
%107 = add nsw i32 %106, -1
store i32 %107, i32* %8
br label %44
108: ; preds = %44
br label %109
109: ; preds = %108
%110 = load i32, i32* %7
%111 = add nsw i32 %110, 1
store i32 %111, i32* %7
br label %37
112: ; preds = %37
ret void
}

LLVM IR (-O2):
define void @cal_tri_inv(double** nocapture %0, double** nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %120
5: ; preds = %3
%6 = zext i32 %2 to i64
%7 = and i64 %6, 1
%8 = icmp eq i32 %2, 1
br i1 %8, label %11, label %9
9: ; preds = %5
%10 = and i64 %6, 4294967294
br label %28
11: ; preds = %28, %5
%12 = phi i64 [ 0, %5 ], [ %48, %28 ]
%13 = icmp eq i64 %7, 0
br i1 %13, label %23, label %14
14: ; preds = %11
%15 = getelementptr inbounds double*, double** %0, i64 %12
%16 = load double*, double** %15
%17 = getelementptr inbounds double, double* %16, i64 %12
%18 = load double, double* %17
%19 = fdiv double 1.000000e+00, %18
%20 = getelementptr inbounds double*, double** %1, i64 %12
%21 = load double*, double** %20
%22 = getelementptr inbounds double, double* %21, i64 %12
store double %19, double* %22
br label %23
23: ; preds = %11, %14
%24 = icmp sgt i32 %2, 1
br i1 %24, label %25, label %120
25: ; preds = %23
%26 = add nsw i32 %2, -1
%27 = zext i32 %26 to i64
br label %51
28: ; preds = %28, %9
%29 = phi i64 [ 0, %9 ], [ %48, %28 ]
%30 = phi i64 [ 0, %9 ], [ %49, %28 ]
%31 = getelementptr inbounds double*, double** %0, i64 %29
%32 = load double*, double** %31
%33 = getelementptr inbounds double, double* %32, i64 %29
%34 = load double, double* %33
%35 = fdiv double 1.000000e+00, %34
%36 = getelementptr inbounds double*, double** %1, i64 %29
%37 = load double*, double** %36
%38 = getelementptr inbounds double, double* %37, i64 %29
store double %35, double* %38
%39 = or i64 %29, 1
%40 = getelementptr inbounds double*, double** %0, i64 %39
%41 = load double*, double** %40
%42 = getelementptr inbounds double, double* %41, i64 %39
%43 = load double, double* %42
%44 = fdiv double 1.000000e+00, %43
%45 = getelementptr inbounds double*, double** %1, i64 %39
%46 = load double*, double** %45
%47 = getelementptr inbounds double, double* %46, i64 %39
store double %44, double* %47
%48 = add nuw nsw i64 %29, 2
%49 = add i64 %30, 2
%50 = icmp eq i64 %49, %10
br i1 %50, label %11, label %28
51: ; preds = %25, %116
%52 = phi i64 [ 1, %25 ], [ %117, %116 ]
%53 = phi i64 [ 0, %25 ], [ %118, %116 ]
%54 = getelementptr inbounds double*, double** %1, i64 %52
%55 = getelementptr inbounds double*, double** %0, i64 %52
br label %60
56: ; preds = %86, %90, %60
%57 = icmp sgt i64 %62, 1
%58 = add nsw i64 %63, -1
%59 = add i64 %61, 1
br i1 %57, label %60, label %116
60: ; preds = %51, %56
%61 = phi i64 [ 0, %51 ], [ %59, %56 ]
%62 = phi i64 [ %52, %51 ], [ %64, %56 ]
%63 = phi i64 [ %53, %51 ], [ %58, %56 ]
%64 = add nsw i64 %62, -1
%65 = icmp sgt i64 %62, %52
br i1 %65, label %56, label %66
66: ; preds = %60
%67 = load double*, double** %54
%68 = getelementptr inbounds double, double* %67, i64 %64
%69 = load double*, double** %55
%70 = getelementptr inbounds double, double* %69, i64 %52
%71 = load double, double* %68
%72 = and i64 %61, 1
%73 = icmp eq i64 %72, 0
br i1 %73, label %74, label %86
74: ; preds = %66
%75 = getelementptr inbounds double, double* %69, i64 %63
%76 = load double, double* %75
%77 = getelementptr inbounds double*, double** %1, i64 %63
%78 = load double*, double** %77
%79 = getelementptr inbounds double, double* %78, i64 %64
%80 = load double, double* %79
%81 = fmul double %76, %80
%82 = load double, double* %70
%83 = fdiv double %81, %82
%84 = fsub double %71, %83
store double %84, double* %68
%85 = add nsw i64 %63, 1
br label %86
86: ; preds = %74, %66
%87 = phi double [ %71, %66 ], [ %84, %74 ]
%88 = phi i64 [ %63, %66 ], [ %85, %74 ]
%89 = icmp eq i64 %61, 0
br i1 %89, label %56, label %90
90: ; preds = %86, %90
%91 = phi double [ %113, %90 ], [ %87, %86 ]
%92 = phi i64 [ %114, %90 ], [ %88, %86 ]
%93 = getelementptr inbounds double, double* %69, i64 %92
%94 = load double, double* %93
%95 = getelementptr inbounds double*, double** %1, i64 %92
%96 = load double*, double** %95
%97 = getelementptr inbounds double, double* %96, i64 %64
%98 = load double, double* %97
%99 = fmul double %94, %98
%100 = load double, double* %70
%101 = fdiv double %99, %100
%102 = fsub double %91, %101
store double %102, double* %68
%103 = add nsw i64 %92, 1
%104 = getelementptr inbounds double, double* %69, i64 %103
%105 = load double, double* %104
%106 = getelementptr inbounds double*, double** %1, i64 %103
%107 = load double*, double** %106
%108 = getelementptr inbounds double, double* %107, i64 %64
%109 = load double, double* %108
%110 = fmul double %105, %109
%111 = load double, double* %70
%112 = fdiv double %110, %111
%113 = fsub double %102, %112
store double %113, double* %68
%114 = add nsw i64 %92, 2
%115 = icmp eq i64 %114, %52
br i1 %115, label %56, label %90
116: ; preds = %56
%117 = add nuw nsw i64 %52, 1
%118 = add nuw nsw i64 %53, 1
%119 = icmp eq i64 %118, %27
br i1 %119, label %120, label %51
120: ; preds = %116, %3, %23
ret void
}