long double matrixMult(long double m1[3][3], long double m2[3][3],
                       long double out[3][3]) {
  int i, j, k;
  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      out[i][j] = 0.0;
      for (k = 0; k < 3; k++)
        out[i][j] += m1[i][k] * m2[k][j];
    }
  }
}


x86 assembly (clang, -O0):
<matrixMult>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x18(%rbp)
mov    %rsi,-0x20(%rbp)
mov    %rdx,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x3,-0x2c(%rbp)
jge    11e5 <matrixMult+0xe5>
movl   $0x0,-0x30(%rbp)
cmpl   $0x3,-0x30(%rbp)
jge    11d2 <matrixMult+0xd2>
mov    -0x28(%rbp),%rcx
movslq -0x2c(%rbp),%rax
lea    (%rax,%rax,2),%rax
shl    $0x4,%rax
add    %rax,%rcx
movslq -0x30(%rbp),%rax
shl    $0x4,%rax
fldz
fstpt  (%rax,%rcx,1)
movl   $0x0,-0x34(%rbp)
cmpl   $0x3,-0x34(%rbp)
jge    11bf <matrixMult+0xbf>
mov    -0x18(%rbp),%rsi
movslq -0x2c(%rbp),%rax
shl    $0x4,%rax
lea    (%rax,%rax,2),%rdx
add    %rdx,%rsi
movslq -0x34(%rbp),%rax
mov    %rax,%rcx
shl    $0x4,%rcx
fldt   (%rcx,%rsi,1)
mov    -0x20(%rbp),%rcx
lea    (%rax,%rax,2),%rax
shl    $0x4,%rax
add    %rax,%rcx
movslq -0x30(%rbp),%rax
shl    $0x4,%rax
fldt   (%rax,%rcx,1)
mov    -0x28(%rbp),%rcx
add    %rdx,%rcx
fldt   (%rax,%rcx,1)
fxch   %st(2)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  (%rax,%rcx,1)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    1159 <matrixMult+0x59>
jmp    11c4 <matrixMult+0xc4>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1128 <matrixMult+0x28>
jmp    11d7 <matrixMult+0xd7>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1117 <matrixMult+0x17>
fldt   -0x10(%rbp)
pop    %rbp
ret

x86 assembly (clang, -O2):
<matrixMult>:
mov    $0x20,%eax
fldz
nopw   0x0(%rax,%rax,1)
fld    %st(0)
fstpt  -0x20(%rdx,%rax,1)
fldt   -0x20(%rdi,%rax,1)
fldt   (%rsi)
fmulp  %st,%st(1)
fadd   %st(1),%st
fld    %st(0)
fstpt  -0x20(%rdx,%rax,1)
fldt   -0x10(%rdi,%rax,1)
fldt   0x30(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fld    %st(0)
fstpt  -0x20(%rdx,%rax,1)
fldt   (%rdi,%rax,1)
fldt   0x60(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  -0x20(%rdx,%rax,1)
fld    %st(0)
fstpt  -0x10(%rdx,%rax,1)
fldt   -0x20(%rdi,%rax,1)
fldt   0x10(%rsi)
fmulp  %st,%st(1)
fadd   %st(1),%st
fld    %st(0)
fstpt  -0x10(%rdx,%rax,1)
fldt   -0x10(%rdi,%rax,1)
fldt   0x40(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fld    %st(0)
fstpt  -0x10(%rdx,%rax,1)
fldt   (%rdi,%rax,1)
fldt   0x70(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  -0x10(%rdx,%rax,1)
fld    %st(0)
fstpt  (%rdx,%rax,1)
fldt   -0x20(%rdi,%rax,1)
fldt   0x20(%rsi)
fmulp  %st,%st(1)
fadd   %st(1),%st
fld    %st(0)
fstpt  (%rdx,%rax,1)
fldt   -0x10(%rdi,%rax,1)
fldt   0x50(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fld    %st(0)
fstpt  (%rdx,%rax,1)
fldt   (%rdi,%rax,1)
fldt   0x80(%rsi)
fmulp  %st,%st(1)
faddp  %st,%st(1)
fstpt  (%rdx,%rax,1)
add    $0x30,%rax
cmp    $0xb0,%rax
jne    1110 <matrixMult+0x10>
ret

LLVM IR (-O0):
define x86_fp80 @matrixMult([3 x x86_fp80]* %0, [3 x x86_fp80]* %1, [3 x x86_fp80]* %2) {
%4 = alloca x86_fp80
%5 = alloca [3 x x86_fp80]*
%6 = alloca [3 x x86_fp80]*
%7 = alloca [3 x x86_fp80]*
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
store [3 x x86_fp80]* %0, [3 x x86_fp80]** %5
store [3 x x86_fp80]* %1, [3 x x86_fp80]** %6
store [3 x x86_fp80]* %2, [3 x x86_fp80]** %7
store i32 0, i32* %8
br label %11
11: ; preds = %63, %3
%12 = load i32, i32* %8
%13 = icmp slt i32 %12, 3
br i1 %13, label %14, label %66
14: ; preds = %11
store i32 0, i32* %9
br label %15
15: ; preds = %59, %14
%16 = load i32, i32* %9
%17 = icmp slt i32 %16, 3
br i1 %17, label %18, label %62
18: ; preds = %15
%19 = load [3 x x86_fp80]*, [3 x x86_fp80]** %7
%20 = load i32, i32* %8
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %19, i64 %21
%23 = load i32, i32* %9
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %22, i64 0, i64 %24
store x86_fp80 0xK00000000000000000000, x86_fp80* %25
store i32 0, i32* %10
br label %26
26: ; preds = %55, %18
%27 = load i32, i32* %10
%28 = icmp slt i32 %27, 3
br i1 %28, label %29, label %58
29: ; preds = %26
%30 = load [3 x x86_fp80]*, [3 x x86_fp80]** %5
%31 = load i32, i32* %8
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %30, i64 %32
%34 = load i32, i32* %10
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %33, i64 0, i64 %35
%37 = load x86_fp80, x86_fp80* %36
%38 = load [3 x x86_fp80]*, [3 x x86_fp80]** %6
%39 = load i32, i32* %10
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %38, i64 %40
%42 = load i32, i32* %9
%43 = sext i32 %42 to i64
%44 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %41, i64 0, i64 %43
%45 = load x86_fp80, x86_fp80* %44
%46 = load [3 x x86_fp80]*, [3 x x86_fp80]** %7
%47 = load i32, i32* %8
%48 = sext i32 %47 to i64
%49 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %46, i64 %48
%50 = load i32, i32* %9
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %49, i64 0, i64 %51
%53 = load x86_fp80, x86_fp80* %52
%54 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %37, x86_fp80 %45, x86_fp80 %53)
store x86_fp80 %54, x86_fp80* %52
br label %55
55: ; preds = %29
%56 = load i32, i32* %10
%57 = add nsw i32 %56, 1
store i32 %57, i32* %10
br label %26
58: ; preds = %26
br label %59
59: ; preds = %58
%60 = load i32, i32* %9
%61 = add nsw i32 %60, 1
store i32 %61, i32* %9
br label %15
62: ; preds = %15
br label %63
63: ; preds = %62
%64 = load i32, i32* %8
%65 = add nsw i32 %64, 1
store i32 %65, i32* %8
br label %11
66: ; preds = %11
%67 = load x86_fp80, x86_fp80* %4
ret x86_fp80 %67
}

LLVM IR (-O2):
define x86_fp80 @matrixMult([3 x x86_fp80]* nocapture %0, [3 x x86_fp80]* nocapture %1, [3 x x86_fp80]* nocapture %2) {
%4 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 0, i64 0
%5 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 1, i64 0
%6 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 2, i64 0
%7 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 0, i64 1
%8 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 1, i64 1
%9 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 2, i64 1
%10 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 0, i64 2
%11 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 1, i64 2
%12 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %1, i64 2, i64 2
br label %13
13: ; preds = %3, %13
%14 = phi i64 [ 0, %3 ], [ %48, %13 ]
%15 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %0, i64 %14, i64 0
%16 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %2, i64 %14, i64 0
store x86_fp80 0xK00000000000000000000, x86_fp80* %16
%17 = load x86_fp80, x86_fp80* %15
%18 = load x86_fp80, x86_fp80* %4
%19 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %17, x86_fp80 %18, x86_fp80 0xK00000000000000000000)
store x86_fp80 %19, x86_fp80* %16
%20 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %0, i64 %14, i64 1
%21 = load x86_fp80, x86_fp80* %20
%22 = load x86_fp80, x86_fp80* %5
%23 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %21, x86_fp80 %22, x86_fp80 %19)
store x86_fp80 %23, x86_fp80* %16
%24 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %0, i64 %14, i64 2
%25 = load x86_fp80, x86_fp80* %24
%26 = load x86_fp80, x86_fp80* %6
%27 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %25, x86_fp80 %26, x86_fp80 %23)
store x86_fp80 %27, x86_fp80* %16
%28 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %2, i64 %14, i64 1
store x86_fp80 0xK00000000000000000000, x86_fp80* %28
%29 = load x86_fp80, x86_fp80* %15
%30 = load x86_fp80, x86_fp80* %7
%31 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %29, x86_fp80 %30, x86_fp80 0xK00000000000000000000)
store x86_fp80 %31, x86_fp80* %28
%32 = load x86_fp80, x86_fp80* %20
%33 = load x86_fp80, x86_fp80* %8
%34 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %32, x86_fp80 %33, x86_fp80 %31)
store x86_fp80 %34, x86_fp80* %28
%35 = load x86_fp80, x86_fp80* %24
%36 = load x86_fp80, x86_fp80* %9
%37 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %35, x86_fp80 %36, x86_fp80 %34)
store x86_fp80 %37, x86_fp80* %28
%38 = getelementptr inbounds [3 x x86_fp80], [3 x x86_fp80]* %2, i64 %14, i64 2
store x86_fp80 0xK00000000000000000000, x86_fp80* %38
%39 = load x86_fp80, x86_fp80* %15
%40 = load x86_fp80, x86_fp80* %10
%41 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %39, x86_fp80 %40, x86_fp80 0xK00000000000000000000)
store x86_fp80 %41, x86_fp80* %38
%42 = load x86_fp80, x86_fp80* %20
%43 = load x86_fp80, x86_fp80* %11
%44 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %42, x86_fp80 %43, x86_fp80 %41)
store x86_fp80 %44, x86_fp80* %38
%45 = load x86_fp80, x86_fp80* %24
%46 = load x86_fp80, x86_fp80* %12
%47 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %45, x86_fp80 %46, x86_fp80 %44)
store x86_fp80 %47, x86_fp80* %38
%48 = add nuw nsw i64 %14, 1
%49 = icmp eq i64 %48, 3
br i1 %49, label %50, label %13
50: ; preds = %13
ret x86_fp80 undef
}