void mul_LU(int n, const double *lu, double *a) {
  int i;
  for (i = 0; i < n; i++) {
    int j;
    for (j = 0; j < n; j++) {
      a[i * n + j] = 0.0;
      int k;
      for (k = 0; k < n; k++) {
        if (i < k)
          continue;
        if (k > j)
          continue;
        if (i == k) {
          a[i * n + j] += lu[k * n + j];
        } else {
          a[i * n + j] += lu[i * n + k] * lu[k * n + j];
        }
      }
    }
  }
}


x86 assembly (clang, -O0):
<mul_LU>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    124d <mul_LU+0x14d>
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    123a <mul_LU+0x13a>
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1227 <mul_LU+0x127>
mov    -0x1c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    1172 <mul_LU+0x72>
jmp    1219 <mul_LU+0x119>
mov    -0x24(%rbp),%eax
cmp    -0x20(%rbp),%eax
jle    1183 <mul_LU+0x83>
jmp    1219 <mul_LU+0x119>
mov    -0x1c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jne    11c5 <mul_LU+0xc5>
mov    -0x10(%rbp),%rax
mov    -0x24(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,(%rax,%rcx,8)
jmp    1214 <mul_LU+0x114>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x24(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
mov    -0x24(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
imul   -0x4(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
jmp    1219 <mul_LU+0x119>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    1155 <mul_LU+0x55>
jmp    122c <mul_LU+0x12c>
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    1129 <mul_LU+0x29>
jmp    123f <mul_LU+0x13f>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1116 <mul_LU+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<mul_LU>:
push   %r15
push   %r14
push   %rbx
test   %edi,%edi
jle    11a7 <mul_LU+0xa7>
mov    %edi,%r14d
lea    0x0(,%r14,8),%r11
xor    %edi,%edi
mov    %rsi,%r8
jmp    112c <mul_LU+0x2c>
nop
add    $0x1,%rdi
add    %r11,%r8
cmp    %r14,%rdi
je     11a7 <mul_LU+0xa7>
mov    %rdi,%r9
imul   %r14,%r9
mov    %rsi,%r10
xor    %ecx,%ecx
jmp    114d <mul_LU+0x4d>
nopw   0x0(%rax,%rax,1)
add    $0x1,%rcx
add    $0x8,%r10
cmp    %r14,%rcx
je     1120 <mul_LU+0x20>
lea    (%rcx,%r9,1),%r15
movq   $0x0,(%rdx,%r15,8)
xorpd  %xmm0,%xmm0
mov    %r10,%rax
xor    %ebx,%ebx
jmp    1190 <mul_LU+0x90>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movsd  (%r8,%rbx,8),%xmm1
mulsd  (%rax),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rdx,%r15,8)
add    $0x1,%rbx
add    %r11,%rax
cmp    %rbx,%r14
je     1140 <mul_LU+0x40>
cmp    %rbx,%rdi
jb     1184 <mul_LU+0x84>
cmp    %rcx,%rbx
ja     1184 <mul_LU+0x84>
cmp    %rbx,%rdi
jne    1170 <mul_LU+0x70>
addsd  (%rsi,%r15,8),%xmm0
jmp    117e <mul_LU+0x7e>
pop    %rbx
pop    %r14
pop    %r15
ret

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

LLVM IR (-O2):
define void @mul_LU(i32 %0, double* nocapture %1, double* nocapture %2) {
%4 = icmp sgt i32 %0, 0
br i1 %4, label %5, label %48
5: ; preds = %3
%6 = zext i32 %0 to i64
%7 = zext i32 %0 to i64
br label %8
8: ; preds = %45, %5
%9 = phi i64 [ 0, %5 ], [ %46, %45 ]
%10 = mul nsw i64 %9, %6
br label %11
11: ; preds = %42, %8
%12 = phi i64 [ 0, %8 ], [ %43, %42 ]
%13 = add nuw nsw i64 %12, %10
%14 = getelementptr inbounds double, double* %2, i64 %13
store double 0.000000e+00, double* %14
%15 = getelementptr inbounds double, double* %1, i64 %13
br label %16
16: ; preds = %11, %38
%17 = phi double [ 0.000000e+00, %11 ], [ %39, %38 ]
%18 = phi i64 [ 0, %11 ], [ %40, %38 ]
%19 = icmp ult i64 %9, %18
%20 = icmp ugt i64 %18, %12
%21 = select i1 %19, i1 true, i1 %20
br i1 %21, label %38, label %22
22: ; preds = %16
%23 = icmp eq i64 %9, %18
br i1 %23, label %24, label %27
24: ; preds = %22
%25 = load double, double* %15
%26 = fadd double %25, %17
br label %36
27: ; preds = %22
%28 = add nuw nsw i64 %18, %10
%29 = getelementptr inbounds double, double* %1, i64 %28
%30 = load double, double* %29
%31 = mul nsw i64 %18, %6
%32 = add nuw nsw i64 %31, %12
%33 = getelementptr inbounds double, double* %1, i64 %32
%34 = load double, double* %33
%35 = tail call double @llvm.fmuladd.f64(double %30, double %34, double %17)
br label %36
36: ; preds = %27, %24
%37 = phi double [ %26, %24 ], [ %35, %27 ]
store double %37, double* %14
br label %38
38: ; preds = %36, %16
%39 = phi double [ %17, %16 ], [ %37, %36 ]
%40 = add nuw nsw i64 %18, 1
%41 = icmp eq i64 %40, %7
br i1 %41, label %42, label %16
42: ; preds = %38
%43 = add nuw nsw i64 %12, 1
%44 = icmp eq i64 %43, %7
br i1 %44, label %45, label %11
45: ; preds = %42
%46 = add nuw nsw i64 %9, 1
%47 = icmp eq i64 %46, %7
br i1 %47, label %48, label %8
48: ; preds = %45, %3
ret void
}