#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*/ _mm_free(double *);
scalar_t__ _mm_malloc(unsigned int const, int);
int /*<<< orphan*/ dgemm_(char *, char *, int const *, unsigned int const *,
                          int const *, double const *, double const *,
                          int const *, double const *, int const *,
                          double const *, double *, int const *);
int /*<<< orphan*/ memcpy(double *, double *, unsigned int const);
scalar_t__ mysecond();
double time_dgemm_blas(const int M, const unsigned N, const int K,
                       const double alpha, const double *A, const int lda,
                       const double *B, const int ldb, const double beta,
                       double *C, const int ldc) {
  double mflops, mflop_s;
  double secs = -1;
  int num_iterations = 1;
  int i;
  char transa = 'n';
  char transb = 'n';
  double *Ca = (double *)_mm_malloc(N * ldc * sizeof(double), 32);
  double cpu_time = 0;
  for (i = 0; i < num_iterations; ++i) {
    memcpy(Ca, C, N * ldc * sizeof(double));
    cpu_time -= mysecond();
    dgemm_(&transa, &transb, &M, &N, &K, &alpha, A, &lda, B, &ldb, &beta, Ca,
           &ldc);
    cpu_time += mysecond();
  }
  mflops = 2.0 * num_iterations * M * N * K / 1.0e6;
  secs = cpu_time;
  mflop_s = mflops / secs;
  memcpy(C, Ca, N * ldc * sizeof(double));
  _mm_free(Ca);
  return mflop_s;
}


x86 assembly (clang, -O0):
<time_dgemm_blas>:
push   %rbp
mov    %rsp,%rbp
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0xb0,%rsp
mov    0x20(%rbp),%eax
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%eax
mov    %edi,-0x24(%rbp)
mov    %esi,-0x28(%rbp)
mov    %edx,-0x2c(%rbp)
movsd  %xmm0,-0x38(%rbp)
mov    %rcx,-0x40(%rbp)
mov    %r8d,-0x44(%rbp)
mov    %r9,-0x50(%rbp)
movsd  %xmm1,-0x58(%rbp)
movsd  0xe6d(%rip),%xmm0
movsd  %xmm0,-0x70(%rbp)
movl   $0x1,-0x74(%rbp)
movb   $0x6e,-0x79(%rbp)
movb   $0x6e,-0x7a(%rbp)
mov    -0x28(%rbp),%eax
imul   0x20(%rbp),%eax
mov    %eax,%eax
shl    $0x3,%rax
mov    %eax,%edi
mov    $0x20,%esi
call   1060 <_mm_malloc@plt>
mov    %rax,-0x88(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x90(%rbp)
ff
movl   $0x0,-0x78(%rbp)
mov    -0x78(%rbp),%eax
cmp    -0x74(%rbp),%eax
jge    12ac <time_dgemm_blas+0x15c>
mov    -0x88(%rbp),%rdi
mov    0x18(%rbp),%rsi
mov    -0x28(%rbp),%eax
imul   0x20(%rbp),%eax
mov    %eax,%eax
shl    $0x3,%rax
mov    %eax,%edx
call   1050 <memcpy@plt>
mov    $0x0,%al
call   1030 <mysecond@plt>
cvtsi2sd %rax,%xmm1
movsd  -0x90(%rbp),%xmm0
ff
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x90(%rbp)
ff
mov    -0x40(%rbp),%r12
mov    -0x50(%rbp),%r14
mov    -0x88(%rbp),%r10
lea    -0x79(%rbp),%rdi
lea    -0x7a(%rbp),%rsi
lea    -0x24(%rbp),%rdx
lea    -0x28(%rbp),%rcx
lea    -0x2c(%rbp),%r8
lea    -0x38(%rbp),%r9
lea    -0x44(%rbp),%r15
lea    0x10(%rbp),%rbx
lea    -0x58(%rbp),%r11
lea    0x20(%rbp),%rax
mov    %r12,(%rsp)
mov    %r15,0x8(%rsp)
mov    %r14,0x10(%rsp)
mov    %rbx,0x18(%rsp)
mov    %r11,0x20(%rsp)
mov    %r10,0x28(%rsp)
mov    %rax,0x30(%rsp)
call   1040 <dgemm_@plt>
mov    $0x0,%al
call   1030 <mysecond@plt>
cvtsi2sd %rax,%xmm0
addsd  -0x90(%rbp),%xmm0
ff
movsd  %xmm0,-0x90(%rbp)
ff
mov    -0x78(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x78(%rbp)
jmp    11d9 <time_dgemm_blas+0x89>
cvtsi2sdl -0x74(%rbp),%xmm0
addsd  %xmm0,%xmm0
cvtsi2sdl -0x24(%rbp),%xmm1
mulsd  %xmm1,%xmm0
mov    -0x28(%rbp),%eax
cvtsi2sd %rax,%xmm1
mulsd  %xmm1,%xmm0
cvtsi2sdl -0x2c(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xd2d(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x90(%rbp),%xmm0
ff
movsd  %xmm0,-0x70(%rbp)
movsd  -0x60(%rbp),%xmm0
divsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    0x18(%rbp),%rdi
mov    -0x88(%rbp),%rsi
mov    -0x28(%rbp),%eax
imul   0x20(%rbp),%eax
mov    %eax,%eax
shl    $0x3,%rax
mov    %eax,%edx
call   1050 <memcpy@plt>
mov    -0x88(%rbp),%rdi
call   1070 <_mm_free@plt>
movsd  -0x68(%rbp),%xmm0
add    $0xb0,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

x86 assembly (clang, -O2):
<time_dgemm_blas>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x30,%rsp
mov    %r9,%r12
mov    %rcx,%r15
mov    0x68(%rsp),%r14
mov    %edi,0xc(%rsp)
mov    %esi,0x8(%rsp)
mov    %edx,0x4(%rsp)
movsd  %xmm0,0x28(%rsp)
mov    %r8d,0x1c(%rsp)
imul   0x70(%rsp),%esi
movsd  %xmm1,0x20(%rsp)
movb   $0x6e,0x3(%rsp)
movb   $0x6e,0x2(%rsp)
lea    0x0(,%rsi,8),%ebp
mov    %ebp,%edi
mov    $0x20,%esi
call   1060 <_mm_malloc@plt>
mov    %rax,%rbx
mov    %rax,%rdi
mov    %r14,%rsi
mov    %ebp,%edx
call   1050 <memcpy@plt>
xor    %eax,%eax
call   1030 <mysecond@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %rax,%xmm0
xorpd  %xmm1,%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
sub    $0x8,%rsp
lea    0x78(%rsp),%rax
lea    0x28(%rsp),%rbp
lea    0x68(%rsp),%r10
lea    0x24(%rsp),%r11
lea    0xb(%rsp),%rdi
lea    0xa(%rsp),%rsi
lea    0x14(%rsp),%rdx
lea    0x10(%rsp),%rcx
lea    0xc(%rsp),%r8
lea    0x30(%rsp),%r9
push   %rax
push   %rbx
push   %rbp
push   %r10
push   %r12
push   %r11
push   %r15
call   1040 <dgemm_@plt>
add    $0x40,%rsp
xor    %eax,%eax
call   1030 <mysecond@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %rax,%xmm0
addsd  0x10(%rsp),%xmm0
xorps  %xmm1,%xmm1
cvtsi2sdl 0xc(%rsp),%xmm1
addsd  %xmm1,%xmm1
mov    0x8(%rsp),%eax
cvtsi2sd %rax,%xmm2
cvtsi2sdl 0x4(%rsp),%xmm3
mulsd  %xmm1,%xmm2
mulsd  %xmm2,%xmm3
divsd  0xda2(%rip),%xmm3
divsd  %xmm0,%xmm3
movsd  %xmm3,0x10(%rsp)
mov    0x70(%rsp),%edx
imul   %eax,%edx
shl    $0x3,%edx
mov    %r14,%rdi
mov    %rbx,%rsi
call   1050 <memcpy@plt>
mov    %rbx,%rdi
call   1070 <_mm_free@plt>
movsd  0x10(%rsp),%xmm0
add    $0x30,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define double @time_dgemm_blas(i32 %0, i32 %1, i32 %2, double %3, double* %4, i32 %5, double* %6, i32 %7, double %8, double* %9, i32 %10) {
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
%15 = alloca double
%16 = alloca double*
%17 = alloca i32
%18 = alloca double*
%19 = alloca i32
%20 = alloca double
%21 = alloca double*
%22 = alloca i32
%23 = alloca double
%24 = alloca double
%25 = alloca double
%26 = alloca i32
%27 = alloca i32
%28 = alloca i8
%29 = alloca i8
%30 = alloca double*
%31 = alloca double
store i32 %0, i32* %12
store i32 %1, i32* %13
store i32 %2, i32* %14
store double %3, double* %15
store double* %4, double** %16
store i32 %5, i32* %17
store double* %6, double** %18
store i32 %7, i32* %19
store double %8, double* %20
store double* %9, double** %21
store i32 %10, i32* %22
store double -1.000000e+00, double* %25
store i32 1, i32* %26
store i8 110, i8* %28
store i8 110, i8* %29
%32 = load i32, i32* %13
%33 = load i32, i32* %22
%34 = mul i32 %32, %33
%35 = zext i32 %34 to i64
%36 = mul i64 %35, 8
%37 = trunc i64 %36 to i32
%38 = call i64 @_mm_malloc(i32 %37, i32 32)
%39 = inttoptr i64 %38 to double*
store double* %39, double** %30
store double 0.000000e+00, double* %31
store i32 0, i32* %27
br label %40
40: ; preds = %66, %11
%41 = load i32, i32* %27
%42 = load i32, i32* %26
%43 = icmp slt i32 %41, %42
br i1 %43, label %44, label %69
44: ; preds = %40
%45 = load double*, double** %30
%46 = load double*, double** %21
%47 = load i32, i32* %13
%48 = load i32, i32* %22
%49 = mul i32 %47, %48
%50 = zext i32 %49 to i64
%51 = mul i64 %50, 8
%52 = trunc i64 %51 to i32
%53 = call i32 @memcpy(double* %45, double* %46, i32 %52)
%54 = call i64 (...) @mysecond()
%55 = sitofp i64 %54 to double
%56 = load double, double* %31
%57 = fsub double %56, %55
store double %57, double* %31
%58 = load double*, double** %16
%59 = load double*, double** %18
%60 = load double*, double** %30
%61 = call i32 @dgemm_(i8* %28, i8* %29, i32* %12, i32* %13, i32* %14, double* %15, double* %58, i32* %17, double* %59, i32* %19, double* %20, double* %60, i32* %22)
%62 = call i64 (...) @mysecond()
%63 = sitofp i64 %62 to double
%64 = load double, double* %31
%65 = fadd double %64, %63
store double %65, double* %31
br label %66
66: ; preds = %44
%67 = load i32, i32* %27
%68 = add nsw i32 %67, 1
store i32 %68, i32* %27
br label %40
69: ; preds = %40
%70 = load i32, i32* %26
%71 = sitofp i32 %70 to double
%72 = fmul double 2.000000e+00, %71
%73 = load i32, i32* %12
%74 = sitofp i32 %73 to double
%75 = fmul double %72, %74
%76 = load i32, i32* %13
%77 = uitofp i32 %76 to double
%78 = fmul double %75, %77
%79 = load i32, i32* %14
%80 = sitofp i32 %79 to double
%81 = fmul double %78, %80
%82 = fdiv double %81, 1.000000e+06
store double %82, double* %23
%83 = load double, double* %31
store double %83, double* %25
%84 = load double, double* %23
%85 = load double, double* %25
%86 = fdiv double %84, %85
store double %86, double* %24
%87 = load double*, double** %21
%88 = load double*, double** %30
%89 = load i32, i32* %13
%90 = load i32, i32* %22
%91 = mul i32 %89, %90
%92 = zext i32 %91 to i64
%93 = mul i64 %92, 8
%94 = trunc i64 %93 to i32
%95 = call i32 @memcpy(double* %87, double* %88, i32 %94)
%96 = load double*, double** %30
%97 = call i32 @_mm_free(double* %96)
%98 = load double, double* %24
ret double %98
}

LLVM IR (-O2):
define double @time_dgemm_blas(i32 %0, i32 %1, i32 %2, double %3, double* %4, i32 %5, double* %6, i32 %7, double %8, double* %9, i32 %10) {
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
%15 = alloca double
%16 = alloca i32
%17 = alloca i32
%18 = alloca double
%19 = alloca i32
%20 = alloca i8
%21 = alloca i8
store i32 %0, i32* %12
store i32 %1, i32* %13
store i32 %2, i32* %14
store double %3, double* %15
store i32 %5, i32* %16
store i32 %7, i32* %17
store double %8, double* %18
store i32 %10, i32* %19
store i8 110, i8* %20
store i8 110, i8* %21
%22 = shl i32 %1, 3
%23 = mul i32 %22, %10
%24 = tail call i64 @_mm_malloc(i32 %23, i32 32)
%25 = inttoptr i64 %24 to double*
%26 = call i32 @memcpy(double* %25, double* %9, i32 %23)
%27 = call i64 (...) @mysecond()
%28 = sitofp i64 %27 to double
%29 = fsub double 0.000000e+00, %28
%30 = call i32 @dgemm_(i8* %20, i8* %21, i32* %12, i32* %13, i32* %14, double* %15, double* %4, i32* %16, double* %6, i32* %17, double* %18, double* %25, i32* %19)
%31 = call i64 (...) @mysecond()
%32 = sitofp i64 %31 to double
%33 = fadd double %29, %32
%34 = load i32, i32* %12
%35 = sitofp i32 %34 to double
%36 = fmul double %35, 2.000000e+00
%37 = load i32, i32* %13
%38 = uitofp i32 %37 to double
%39 = fmul double %36, %38
%40 = load i32, i32* %14
%41 = sitofp i32 %40 to double
%42 = fmul double %39, %41
%43 = fdiv double %42, 1.000000e+06
%44 = fdiv double %43, %33
%45 = load i32, i32* %19
%46 = shl i32 %37, 3
%47 = mul i32 %46, %45
%48 = call i32 @memcpy(double* %9, double* %25, i32 %47)
%49 = call i32 @_mm_free(double* %25)
ret double %44
}