#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 */

/* Variables and functions */
int /*<<< orphan*/ mcopy(double **, double **);
void mmmul(double A[3][3], double B[3][3], double C[3][3]) {
  double T[3][3];
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 3; ++j) {
      T[i][j] = 0.0;
    }
  }
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 3; ++k) {
        T[i][j] += A[i][k] * B[k][j];
      }
    }
  }
  mcopy(T, C);
}


x86 assembly (clang, -O0):
<mmmul>:
push   %rbp
mov    %rsp,%rbp
sub    $0x80,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movl   $0x0,-0x64(%rbp)
cmpl   $0x3,-0x64(%rbp)
jge    1185 <mmmul+0x75>
movl   $0x0,-0x68(%rbp)
cmpl   $0x3,-0x68(%rbp)
jge    1172 <mmmul+0x62>
movslq -0x64(%rbp),%rcx
lea    -0x60(%rbp),%rax
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
movslq -0x68(%rbp),%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x68(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x68(%rbp)
jmp    113f <mmmul+0x2f>
jmp    1177 <mmmul+0x67>
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    112e <mmmul+0x1e>
movl   $0x0,-0x6c(%rbp)
cmpl   $0x3,-0x6c(%rbp)
jge    1241 <mmmul+0x131>
movl   $0x0,-0x70(%rbp)
cmpl   $0x3,-0x70(%rbp)
jge    122e <mmmul+0x11e>
movl   $0x0,-0x74(%rbp)
cmpl   $0x3,-0x74(%rbp)
jge    121b <mmmul+0x10b>
mov    -0x8(%rbp),%rax
movslq -0x6c(%rbp),%rcx
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
movslq -0x74(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x74(%rbp),%rcx
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
movslq -0x70(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movslq -0x6c(%rbp),%rcx
lea    -0x60(%rbp),%rax
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
movslq -0x70(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x74(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x74(%rbp)
jmp    11ae <mmmul+0x9e>
jmp    1220 <mmmul+0x110>
mov    -0x70(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x70(%rbp)
jmp    119d <mmmul+0x8d>
jmp    1233 <mmmul+0x123>
mov    -0x6c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x6c(%rbp)
jmp    118c <mmmul+0x7c>
lea    -0x60(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1030 <mcopy@plt>
add    $0x80,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<mmmul>:
sub    $0x48,%rsp
xorps  %xmm0,%xmm0
movaps %xmm0,0x30(%rsp)
movaps %xmm0,0x20(%rsp)
movaps %xmm0,0x10(%rsp)
movaps %xmm0,(%rsp)
movq   $0x0,0x40(%rsp)
movupd (%rsi),%xmm5
movupd 0x18(%rsi),%xmm4
movupd 0x30(%rsi),%xmm3
movsd  0x10(%rsi),%xmm10
movsd  0x28(%rsi),%xmm9
movsd  0x40(%rsi),%xmm8
movsd  (%rdi),%xmm1
movsd  0x8(%rdi),%xmm2
movsd  0x10(%rdi),%xmm0
movapd %xmm1,%xmm6
unpcklpd %xmm1,%xmm6
mulpd  %xmm5,%xmm6
addpd  (%rsp),%xmm6
movapd %xmm2,%xmm7
unpcklpd %xmm2,%xmm7
mulpd  %xmm4,%xmm7
addpd  %xmm6,%xmm7
movapd %xmm0,%xmm6
unpcklpd %xmm0,%xmm6
mulpd  %xmm3,%xmm6
addpd  %xmm7,%xmm6
movapd %xmm6,(%rsp)
mulsd  %xmm10,%xmm1
addsd  0x10(%rsp),%xmm1
mulsd  %xmm9,%xmm2
addsd  %xmm1,%xmm2
mulsd  %xmm8,%xmm0
addsd  %xmm2,%xmm0
movsd  %xmm0,0x10(%rsp)
movsd  0x18(%rdi),%xmm0
movsd  0x20(%rdi),%xmm6
movsd  0x28(%rdi),%xmm7
movupd 0x18(%rsp),%xmm1
movapd %xmm0,%xmm2
unpcklpd %xmm0,%xmm2
mulpd  %xmm5,%xmm2
addpd  %xmm1,%xmm2
movapd %xmm6,%xmm1
unpcklpd %xmm6,%xmm1
mulpd  %xmm4,%xmm1
addpd  %xmm2,%xmm1
movapd %xmm7,%xmm2
unpcklpd %xmm7,%xmm2
mulpd  %xmm3,%xmm2
addpd  %xmm1,%xmm2
movupd %xmm2,0x18(%rsp)
mulsd  %xmm10,%xmm0
addsd  0x28(%rsp),%xmm0
mulsd  %xmm9,%xmm6
addsd  %xmm0,%xmm6
mulsd  %xmm8,%xmm7
addsd  %xmm6,%xmm7
movsd  %xmm7,0x28(%rsp)
movsd  0x30(%rdi),%xmm0
movsd  0x38(%rdi),%xmm1
movapd %xmm0,%xmm2
unpcklpd %xmm0,%xmm2
mulpd  %xmm5,%xmm2
addpd  0x30(%rsp),%xmm2
movsd  0x40(%rdi),%xmm5
movapd %xmm1,%xmm6
unpcklpd %xmm1,%xmm6
mulpd  %xmm4,%xmm6
addpd  %xmm2,%xmm6
movapd %xmm5,%xmm2
unpcklpd %xmm5,%xmm2
mulpd  %xmm3,%xmm2
addpd  %xmm6,%xmm2
movapd %xmm2,0x30(%rsp)
mulsd  %xmm10,%xmm0
addsd  0x40(%rsp),%xmm0
mulsd  %xmm9,%xmm1
addsd  %xmm0,%xmm1
mulsd  %xmm8,%xmm5
addsd  %xmm1,%xmm5
movsd  %xmm5,0x40(%rsp)
mov    %rsp,%rdi
mov    %rdx,%rsi
call   1030 <mcopy@plt>
add    $0x48,%rsp
ret

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

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