#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 */
typedef int /*<<< orphan*/ matB;
typedef int /*<<< orphan*/ matA;

/* Variables and functions */
int /*<<< orphan*/ memcpy(double *, double const *, int);
void babl_matrix_mul_matrix(const double *matA_, const double *matB_,
                            double *out) {
  int i, j;
  double matA[9];
  double matB[9];
  double t1, t2, t3;
  memcpy(matA, matA_, sizeof(matA));
  memcpy(matB, matB_, sizeof(matB));
  for (i = 0; i < 3; i++) {
    t1 = matA[i * 3 + 0];
    t2 = matA[i * 3 + 1];
    t3 = matA[i * 3 + 2];
    for (j = 0; j < 3; j++) {
      out[i * 3 + j] = t1 * matB[0 * 3 + j];
      out[i * 3 + j] += t2 * matB[1 * 3 + j];
      out[i * 3 + j] += t3 * matB[2 * 3 + j];
    }
  }
}


x86 assembly (clang, -O0):
<babl_matrix_mul_matrix>:
push   %rbp
mov    %rsp,%rbp
sub    $0xe0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
lea    -0x70(%rbp),%rdi
mov    -0x8(%rbp),%rsi
mov    $0x48,%edx
call   1030 <memcpy@plt>
lea    -0xc0(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    $0x48,%edx
call   1030 <memcpy@plt>
movl   $0x0,-0x1c(%rbp)
cmpl   $0x3,-0x1c(%rbp)
jge    1274 <babl_matrix_mul_matrix+0x164>
imul   $0x3,-0x1c(%rbp),%eax
add    $0x0,%eax
cltq
movsd  -0x70(%rbp,%rax,8),%xmm0
movsd  %xmm0,-0xc8(%rbp)
ff
imul   $0x3,-0x1c(%rbp),%eax
add    $0x1,%eax
cltq
movsd  -0x70(%rbp,%rax,8),%xmm0
movsd  %xmm0,-0xd0(%rbp)
ff
imul   $0x3,-0x1c(%rbp),%eax
add    $0x2,%eax
cltq
movsd  -0x70(%rbp,%rax,8),%xmm0
movsd  %xmm0,-0xd8(%rbp)
ff
movl   $0x0,-0x20(%rbp)
cmpl   $0x3,-0x20(%rbp)
jge    1261 <babl_matrix_mul_matrix+0x151>
movsd  -0xc8(%rbp),%xmm0
ff
mov    -0x20(%rbp),%eax
add    $0x0,%eax
cltq
mulsd  -0xc0(%rbp,%rax,8),%xmm0
ff ff
mov    -0x18(%rbp),%rax
imul   $0x3,-0x1c(%rbp),%ecx
add    -0x20(%rbp),%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
movsd  -0xd0(%rbp),%xmm0
ff
mov    -0x20(%rbp),%eax
add    $0x3,%eax
cltq
movsd  -0xc0(%rbp,%rax,8),%xmm2
ff ff
mov    -0x18(%rbp),%rax
imul   $0x3,-0x1c(%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)
movsd  -0xd8(%rbp),%xmm0
ff
mov    -0x20(%rbp),%eax
add    $0x6,%eax
cltq
movsd  -0xc0(%rbp,%rax,8),%xmm2
ff ff
mov    -0x18(%rbp),%rax
imul   $0x3,-0x1c(%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)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    11ab <babl_matrix_mul_matrix+0x9b>
jmp    1266 <babl_matrix_mul_matrix+0x156>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1155 <babl_matrix_mul_matrix+0x45>
add    $0xe0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<babl_matrix_mul_matrix>:
push   %r14
push   %rbx
sub    $0x98,%rsp
mov    %rdx,%r14
mov    %rsi,%rbx
mov    %rdi,%rsi
mov    %rsp,%rdi
mov    $0x48,%edx
call   1030 <memcpy@plt>
lea    0x50(%rsp),%rdi
mov    %rbx,%rsi
mov    $0x48,%edx
call   1030 <memcpy@plt>
movapd 0x50(%rsp),%xmm11
movsd  (%rsp),%xmm5
movsd  0x8(%rsp),%xmm2
movsd  0x10(%rsp),%xmm6
movapd %xmm5,%xmm3
unpcklpd %xmm5,%xmm3
mulpd  %xmm11,%xmm3
movupd 0x68(%rsp),%xmm12
movapd %xmm2,%xmm4
unpcklpd %xmm2,%xmm4
mulpd  %xmm12,%xmm4
addpd  %xmm3,%xmm4
movapd 0x80(%rsp),%xmm3
movapd %xmm6,%xmm7
unpcklpd %xmm6,%xmm7
mulpd  %xmm3,%xmm7
addpd  %xmm4,%xmm7
movupd %xmm7,(%r14)
movsd  0x60(%rsp),%xmm10
movsd  0x78(%rsp),%xmm9
movsd  0x90(%rsp),%xmm8
movsd  0x18(%rsp),%xmm0
movsd  0x20(%rsp),%xmm4
movsd  0x28(%rsp),%xmm7
unpcklpd %xmm0,%xmm5
movapd %xmm10,%xmm1
unpcklpd %xmm11,%xmm1
mulpd  %xmm5,%xmm1
unpcklpd %xmm4,%xmm2
movapd %xmm9,%xmm5
unpcklpd %xmm12,%xmm5
mulpd  %xmm2,%xmm5
addpd  %xmm1,%xmm5
unpcklpd %xmm7,%xmm6
movapd %xmm8,%xmm1
unpcklpd %xmm3,%xmm1
mulpd  %xmm6,%xmm1
addpd  %xmm5,%xmm1
movupd %xmm1,0x10(%r14)
unpcklpd %xmm0,%xmm0
movapd %xmm11,%xmm1
shufpd $0x1,%xmm10,%xmm1
mulpd  %xmm0,%xmm1
unpcklpd %xmm4,%xmm4
movapd %xmm12,%xmm0
shufpd $0x1,%xmm9,%xmm0
mulpd  %xmm4,%xmm0
addpd  %xmm1,%xmm0
unpcklpd %xmm7,%xmm7
movapd %xmm3,%xmm1
shufpd $0x1,%xmm8,%xmm1
mulpd  %xmm7,%xmm1
addpd  %xmm0,%xmm1
movupd %xmm1,0x20(%r14)
movsd  0x30(%rsp),%xmm0
movsd  0x38(%rsp),%xmm1
movsd  0x40(%rsp),%xmm2
movapd %xmm0,%xmm4
unpcklpd %xmm0,%xmm4
mulpd  %xmm11,%xmm4
movapd %xmm1,%xmm5
unpcklpd %xmm1,%xmm5
mulpd  %xmm12,%xmm5
addpd  %xmm4,%xmm5
movapd %xmm2,%xmm4
unpcklpd %xmm2,%xmm4
mulpd  %xmm3,%xmm4
addpd  %xmm5,%xmm4
movupd %xmm4,0x30(%r14)
mulsd  %xmm10,%xmm0
mulsd  %xmm9,%xmm1
addsd  %xmm0,%xmm1
mulsd  %xmm8,%xmm2
addsd  %xmm1,%xmm2
movsd  %xmm2,0x40(%r14)
add    $0x98,%rsp
pop    %rbx
pop    %r14
ret

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

LLVM IR (-O2):
define void @babl_matrix_mul_matrix(double* %0, double* %1, double* nocapture writeonly %2) {
%4 = alloca [9 x double]
%5 = alloca [9 x double]
%6 = bitcast [9 x double]* %4 to i8*
%7 = bitcast [9 x double]* %5 to i8*
%8 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 0
%9 = call i32 @memcpy(double* %8, double* %0, i32 72)
%10 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 0
%11 = call i32 @memcpy(double* %10, double* %1, i32 72)
%12 = load double, double* %8
%13 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 1
%14 = load double, double* %13
%15 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 2
%16 = load double, double* %15
%17 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 3
%18 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 6
%19 = bitcast [9 x double]* %5 to <2 x double>*
%20 = load <2 x double>, <2 x double>* %19
%21 = insertelement <2 x double> poison, double %12, i64 0
%22 = shufflevector <2 x double> %21, <2 x double> poison, <2 x i32> zeroinitializer
%23 = fmul <2 x double> %22, %20
%24 = bitcast double* %17 to <2 x double>*
%25 = load <2 x double>, <2 x double>* %24
%26 = insertelement <2 x double> poison, double %14, i64 0
%27 = shufflevector <2 x double> %26, <2 x double> poison, <2 x i32> zeroinitializer
%28 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %27, <2 x double> %25, <2 x double> %23)
%29 = bitcast double* %18 to <2 x double>*
%30 = load <2 x double>, <2 x double>* %29
%31 = insertelement <2 x double> poison, double %16, i64 0
%32 = shufflevector <2 x double> %31, <2 x double> poison, <2 x i32> zeroinitializer
%33 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %32, <2 x double> %30, <2 x double> %28)
%34 = bitcast double* %2 to <2 x double>*
store <2 x double> %33, <2 x double>* %34
%35 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 2
%36 = load double, double* %35
%37 = getelementptr inbounds double, double* %2, i64 2
%38 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 5
%39 = load double, double* %38
%40 = getelementptr inbounds [9 x double], [9 x double]* %5, i64 0, i64 8
%41 = load double, double* %40
%42 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 3
%43 = load double, double* %42
%44 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 4
%45 = load double, double* %44
%46 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 5
%47 = load double, double* %46
%48 = insertelement <2 x double> %21, double %43, i64 1
%49 = insertelement <2 x double> poison, double %36, i64 0
%50 = shufflevector <2 x double> %49, <2 x double> %20, <2 x i32> <i32 0, i32 2>
%51 = fmul <2 x double> %48, %50
%52 = insertelement <2 x double> %26, double %45, i64 1
%53 = insertelement <2 x double> poison, double %39, i64 0
%54 = shufflevector <2 x double> %53, <2 x double> %25, <2 x i32> <i32 0, i32 2>
%55 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %52, <2 x double> %54, <2 x double> %51)
%56 = insertelement <2 x double> %31, double %47, i64 1
%57 = insertelement <2 x double> poison, double %41, i64 0
%58 = shufflevector <2 x double> %57, <2 x double> %30, <2 x i32> <i32 0, i32 2>
%59 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %56, <2 x double> %58, <2 x double> %55)
%60 = bitcast double* %37 to <2 x double>*
store <2 x double> %59, <2 x double>* %60
%61 = extractelement <2 x double> %20, i64 1
%62 = getelementptr inbounds double, double* %2, i64 4
%63 = extractelement <2 x double> %25, i64 1
%64 = extractelement <2 x double> %30, i64 1
%65 = insertelement <2 x double> poison, double %43, i64 0
%66 = shufflevector <2 x double> %65, <2 x double> poison, <2 x i32> zeroinitializer
%67 = insertelement <2 x double> poison, double %61, i64 0
%68 = insertelement <2 x double> %67, double %36, i64 1
%69 = fmul <2 x double> %66, %68
%70 = insertelement <2 x double> poison, double %45, i64 0
%71 = shufflevector <2 x double> %70, <2 x double> poison, <2 x i32> zeroinitializer
%72 = insertelement <2 x double> poison, double %63, i64 0
%73 = insertelement <2 x double> %72, double %39, i64 1
%74 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %71, <2 x double> %73, <2 x double> %69)
%75 = insertelement <2 x double> poison, double %47, i64 0
%76 = shufflevector <2 x double> %75, <2 x double> poison, <2 x i32> zeroinitializer
%77 = insertelement <2 x double> poison, double %64, i64 0
%78 = insertelement <2 x double> %77, double %41, i64 1
%79 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %76, <2 x double> %78, <2 x double> %74)
%80 = bitcast double* %62 to <2 x double>*
store <2 x double> %79, <2 x double>* %80
%81 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 6
%82 = load double, double* %81
%83 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 7
%84 = load double, double* %83
%85 = getelementptr inbounds [9 x double], [9 x double]* %4, i64 0, i64 8
%86 = load double, double* %85
%87 = getelementptr inbounds double, double* %2, i64 6
%88 = insertelement <2 x double> poison, double %82, i64 0
%89 = shufflevector <2 x double> %88, <2 x double> poison, <2 x i32> zeroinitializer
%90 = fmul <2 x double> %89, %20
%91 = insertelement <2 x double> poison, double %84, i64 0
%92 = shufflevector <2 x double> %91, <2 x double> poison, <2 x i32> zeroinitializer
%93 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %92, <2 x double> %25, <2 x double> %90)
%94 = insertelement <2 x double> poison, double %86, i64 0
%95 = shufflevector <2 x double> %94, <2 x double> poison, <2 x i32> zeroinitializer
%96 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %95, <2 x double> %30, <2 x double> %93)
%97 = bitcast double* %87 to <2 x double>*
store <2 x double> %96, <2 x double>* %97
%98 = fmul double %82, %36
%99 = getelementptr inbounds double, double* %2, i64 8
%100 = call double @llvm.fmuladd.f64(double %84, double %39, double %98)
%101 = call double @llvm.fmuladd.f64(double %86, double %41, double %100)
store double %101, double* %99
ret void
}