void cpu_gemm_tt(int TA, int TB, int M, int N, int K, float ALPHA, float *A,
                 int lda, float *B, int ldb, float BETA, float *C, int ldc) {
  int i, j, k;
  for (i = 0; i < M; ++i) {
    for (j = 0; j < N; ++j) {
      for (k = 0; k < K; ++k) {
        C[i * ldc + j] += ALPHA * A[i + k * lda] * B[k + j * ldb];
      }
    }
  }
}


x86 assembly (clang, -O0):
<cpu_gemm_tt>:
push   %rbp
mov    %rsp,%rbp
mov    0x30(%rbp),%eax
mov    0x28(%rbp),%rax
mov    0x20(%rbp),%eax
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%eax
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %edx,-0xc(%rbp)
mov    %ecx,-0x10(%rbp)
mov    %r8d,-0x14(%rbp)
movss  %xmm0,-0x18(%rbp)
mov    %r9,-0x20(%rbp)
movss  %xmm1,-0x24(%rbp)
movl   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    11f8 <cpu_gemm_tt+0xf8>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x10(%rbp),%eax
jge    11e5 <cpu_gemm_tt+0xe5>
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11d2 <cpu_gemm_tt+0xd2>
movss  -0x18(%rbp),%xmm0
mov    -0x20(%rbp),%rax
mov    -0x28(%rbp),%ecx
mov    -0x30(%rbp),%edx
imul   0x10(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
mulss  (%rax,%rcx,4),%xmm0
mov    0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    -0x2c(%rbp),%edx
imul   0x20(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm2
mov    0x28(%rbp),%rax
mov    -0x28(%rbp),%ecx
imul   0x30(%rbp),%ecx
add    -0x2c(%rbp),%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,(%rax,%rcx,4)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1160 <cpu_gemm_tt+0x60>
jmp    11d7 <cpu_gemm_tt+0xd7>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    114d <cpu_gemm_tt+0x4d>
jmp    11ea <cpu_gemm_tt+0xea>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    113a <cpu_gemm_tt+0x3a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<cpu_gemm_tt>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %r9,-0x30(%rsp)
mov    %ecx,-0x44(%rsp)
test   %edx,%edx
jle    12a5 <cpu_gemm_tt+0x1a5>
mov    0x50(%rsp),%rax
mov    0x40(%rsp),%rcx
movslq 0x38(%rsp),%rdi
movslq 0x48(%rsp),%rbp
movslq 0x58(%rsp),%rsi
mov    %rsi,-0x18(%rsp)
mov    %edx,%edx
mov    %rdx,-0x10(%rsp)
mov    -0x44(%rsp),%r14d
mov    %r8d,%r11d
mov    %r11d,%edx
and    $0xfffffffe,%edx
lea    0x0(,%rdi,8),%rsi
add    $0x4,%rcx
mov    %rcx,-0x20(%rsp)
mov    %rbp,-0x8(%rsp)
lea    0x0(,%rbp,4),%rbx
xor    %ecx,%ecx
mov    %rcx,-0x40(%rsp)
mov    -0x30(%rsp),%rcx
mov    %rcx,-0x28(%rsp)
mov    %r8d,-0x34(%rsp)
jmp    11b2 <cpu_gemm_tt+0xb2>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mov    -0x40(%rsp),%rbp
add    $0x1,%rbp
addq   $0x4,-0x28(%rsp)
mov    %rbp,%rcx
mov    %rbp,-0x40(%rsp)
cmp    -0x10(%rsp),%rbp
je     12a5 <cpu_gemm_tt+0x1a5>
cmpl   $0x0,-0x44(%rsp)
jle    1190 <cpu_gemm_tt+0x90>
mov    -0x40(%rsp),%r12
imul   -0x18(%rsp),%r12
mov    -0x20(%rsp),%rcx
xor    %r10d,%r10d
jmp    11dc <cpu_gemm_tt+0xdc>
xchg   %ax,%ax
add    $0x1,%r10
add    %rbx,%rcx
cmp    %r14,%r10
je     1190 <cpu_gemm_tt+0x90>
test   %r8d,%r8d
jle    11d0 <cpu_gemm_tt+0xd0>
lea    (%r10,%r12,1),%r13
movss  (%rax,%r13,4),%xmm1
cmp    $0x1,%r8d
jne    1200 <cpu_gemm_tt+0x100>
xor    %r15d,%r15d
jmp    1250 <cpu_gemm_tt+0x150>
cs nopw 0x0(%rax,%rax,1)
mov    -0x28(%rsp),%r9
xor    %r15d,%r15d
nopl   0x0(%rax,%rax,1)
movss  (%r9),%xmm2
mulss  %xmm0,%xmm2
mulss  -0x4(%rcx,%r15,4),%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,(%rax,%r13,4)
movss  (%r9,%rdi,4),%xmm1
mulss  %xmm0,%xmm1
mulss  (%rcx,%r15,4),%xmm1
addss  %xmm2,%xmm1
movss  %xmm1,(%rax,%r13,4)
add    $0x2,%r15
add    %rsi,%r9
cmp    %r15,%rdx
jne    1210 <cpu_gemm_tt+0x110>
test   $0x1,%r11b
je     11d0 <cpu_gemm_tt+0xd0>
mov    %r10,%r9
imul   -0x8(%rsp),%r9
mov    %r15,%rbp
imul   %rdi,%rbp
add    -0x40(%rsp),%rbp
mov    %rbx,%r8
mov    -0x30(%rsp),%rbx
movss  (%rbx,%rbp,4),%xmm2
mulss  %xmm0,%xmm2
add    %r15,%r9
mov    0x40(%rsp),%rbx
mulss  (%rbx,%r9,4),%xmm2
mov    %r8,%rbx
mov    -0x34(%rsp),%r8d
addss  %xmm1,%xmm2
movss  %xmm2,(%rax,%r13,4)
jmp    11d0 <cpu_gemm_tt+0xd0>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
define void @cpu_gemm_tt(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, float %5, float* nocapture %6, i32 %7, float* nocapture %8, i32 %9, float %10, float* nocapture %11, i32 %12) {
%14 = icmp sgt i32 %2, 0
br i1 %14, label %15, label %84
15: ; preds = %13
%16 = icmp sgt i32 %3, 0
%17 = icmp sgt i32 %4, 0
%18 = sext i32 %7 to i64
%19 = sext i32 %9 to i64
%20 = sext i32 %12 to i64
%21 = zext i32 %2 to i64
%22 = zext i32 %3 to i64
%23 = zext i32 %4 to i64
%24 = and i64 %23, 1
%25 = icmp eq i32 %4, 1
%26 = and i64 %23, 4294967294
%27 = icmp eq i64 %24, 0
br label %28
28: ; preds = %15, %81
%29 = phi i64 [ 0, %15 ], [ %82, %81 ]
br i1 %16, label %30, label %81
30: ; preds = %28
%31 = mul nsw i64 %29, %20
br label %32
32: ; preds = %30, %78
%33 = phi i64 [ 0, %30 ], [ %79, %78 ]
br i1 %17, label %34, label %78
34: ; preds = %32
%35 = mul nsw i64 %33, %19
%36 = add nsw i64 %33, %31
%37 = getelementptr inbounds float, float* %11, i64 %36
%38 = load float, float* %37
br i1 %25, label %65, label %39
39: ; preds = %34, %39
%40 = phi float [ %61, %39 ], [ %38, %34 ]
%41 = phi i64 [ %62, %39 ], [ 0, %34 ]
%42 = phi i64 [ %63, %39 ], [ 0, %34 ]
%43 = mul nsw i64 %41, %18
%44 = add nsw i64 %43, %29
%45 = getelementptr inbounds float, float* %6, i64 %44
%46 = load float, float* %45
%47 = fmul float %46, %5
%48 = add nsw i64 %41, %35
%49 = getelementptr inbounds float, float* %8, i64 %48
%50 = load float, float* %49
%51 = tail call float @llvm.fmuladd.f32(float %47, float %50, float %40)
store float %51, float* %37
%52 = or i64 %41, 1
%53 = mul nsw i64 %52, %18
%54 = add nsw i64 %53, %29
%55 = getelementptr inbounds float, float* %6, i64 %54
%56 = load float, float* %55
%57 = fmul float %56, %5
%58 = add nsw i64 %52, %35
%59 = getelementptr inbounds float, float* %8, i64 %58
%60 = load float, float* %59
%61 = tail call float @llvm.fmuladd.f32(float %57, float %60, float %51)
store float %61, float* %37
%62 = add nuw nsw i64 %41, 2
%63 = add i64 %42, 2
%64 = icmp eq i64 %63, %26
br i1 %64, label %65, label %39
65: ; preds = %39, %34
%66 = phi float [ %38, %34 ], [ %61, %39 ]
%67 = phi i64 [ 0, %34 ], [ %62, %39 ]
br i1 %27, label %78, label %68
68: ; preds = %65
%69 = mul nsw i64 %67, %18
%70 = add nsw i64 %69, %29
%71 = getelementptr inbounds float, float* %6, i64 %70
%72 = load float, float* %71
%73 = fmul float %72, %5
%74 = add nsw i64 %67, %35
%75 = getelementptr inbounds float, float* %8, i64 %74
%76 = load float, float* %75
%77 = tail call float @llvm.fmuladd.f32(float %73, float %76, float %66)
store float %77, float* %37
br label %78
78: ; preds = %68, %65, %32
%79 = add nuw nsw i64 %33, 1
%80 = icmp eq i64 %79, %22
br i1 %80, label %81, label %32
81: ; preds = %78, %28
%82 = add nuw nsw i64 %29, 1
%83 = icmp eq i64 %82, %21
br i1 %83, label %84, label %28
84: ; preds = %81, %13
ret void
}