void cpu_gemm_nt(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) {
      register float sum = 0;
      for (k = 0; k < K; ++k) {
        sum += ALPHA * A[i * lda + k] * B[k + j * ldb];
      }
      C[i * ldc + j] += sum;
    }
  }
}


x86 assembly (clang, -O0):
<cpu_gemm_nt>:
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    1208 <cpu_gemm_nt+0x108>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x10(%rbp),%eax
jge    11f5 <cpu_gemm_nt+0xf5>
xorps  %xmm0,%xmm0
movss  %xmm0,-0x34(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11c7 <cpu_gemm_nt+0xc7>
movss  -0x18(%rbp),%xmm0
mov    -0x20(%rbp),%rax
mov    -0x28(%rbp),%ecx
imul   0x10(%rbp),%ecx
add    -0x30(%rbp),%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
movss  -0x34(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x34(%rbp)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1168 <cpu_gemm_nt+0x68>
movss  -0x34(%rbp),%xmm0
mov    0x28(%rbp),%rax
mov    -0x28(%rbp),%ecx
imul   0x30(%rbp),%ecx
add    -0x2c(%rbp),%ecx
movslq %ecx,%rcx
addss  (%rax,%rcx,4),%xmm0
movss  %xmm0,(%rax,%rcx,4)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    114d <cpu_gemm_nt+0x4d>
jmp    11fa <cpu_gemm_nt+0xfa>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    113a <cpu_gemm_nt+0x3a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<cpu_gemm_nt>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %r9,-0x38(%rsp)
mov    %ecx,-0x44(%rsp)
test   %edx,%edx
jle    127c <cpu_gemm_nt+0x17c>
mov    0x50(%rsp),%rax
mov    0x40(%rsp),%r9
movslq 0x48(%rsp),%rbp
movslq 0x38(%rsp),%rsi
movslq 0x58(%rsp),%rcx
mov    %rcx,-0x28(%rsp)
mov    %edx,%ecx
mov    %rcx,-0x10(%rsp)
mov    -0x44(%rsp),%ebx
mov    %r8d,%r14d
mov    %r14d,%edx
and    $0xfffffffe,%edx
mov    -0x38(%rsp),%rcx
lea    0x4(%rcx),%rdi
mov    %rsi,-0x20(%rsp)
lea    0x0(,%rsi,4),%rcx
mov    %rcx,-0x18(%rsp)
lea    0x4(%r9),%rcx
mov    %rcx,-0x30(%rsp)
mov    %rbp,-0x8(%rsp)
lea    0x0(,%rbp,4),%r11
xor    %ecx,%ecx
mov    %rcx,-0x40(%rsp)
jmp    11b1 <cpu_gemm_nt+0xb1>
nopw   0x0(%rax,%rax,1)
mov    -0x40(%rsp),%rsi
add    $0x1,%rsi
add    -0x18(%rsp),%rdi
mov    %rsi,%rcx
mov    %rsi,-0x40(%rsp)
cmp    -0x10(%rsp),%rsi
je     127c <cpu_gemm_nt+0x17c>
cmpl   $0x0,-0x44(%rsp)
jle    1190 <cpu_gemm_nt+0x90>
mov    -0x40(%rsp),%rbp
mov    %rbp,%r10
imul   -0x20(%rsp),%r10
imul   -0x28(%rsp),%rbp
mov    -0x30(%rsp),%rcx
xor    %r13d,%r13d
jmp    11fc <cpu_gemm_nt+0xfc>
cs nopw 0x0(%rax,%rax,1)
mov    %r13,%rsi
add    %rbp,%rsi
addss  (%rax,%rsi,4),%xmm1
movss  %xmm1,(%rax,%rsi,4)
add    $0x1,%r13
add    %r11,%rcx
cmp    %rbx,%r13
je     1190 <cpu_gemm_nt+0x90>
xorps  %xmm1,%xmm1
test   %r8d,%r8d
jle    11e0 <cpu_gemm_nt+0xe0>
xor    %r15d,%r15d
cmp    $0x1,%r8d
je     1243 <cpu_gemm_nt+0x143>
nopl   (%rax)
movss  -0x4(%rdi,%r15,4),%xmm2
mulss  %xmm0,%xmm2
mulss  -0x4(%rcx,%r15,4),%xmm2
addss  %xmm1,%xmm2
movss  (%rdi,%r15,4),%xmm1
mulss  %xmm0,%xmm1
mulss  (%rcx,%r15,4),%xmm1
addss  %xmm2,%xmm1
add    $0x2,%r15
cmp    %r15,%rdx
jne    1210 <cpu_gemm_nt+0x110>
test   $0x1,%r14b
je     11e0 <cpu_gemm_nt+0xe0>
mov    %r13,%r12
imul   -0x8(%rsp),%r12
lea    (%r15,%r10,1),%r9
mov    -0x38(%rsp),%rsi
movss  (%rsi,%r9,4),%xmm2
mulss  %xmm0,%xmm2
add    %r15,%r12
mov    0x40(%rsp),%rsi
mulss  (%rsi,%r12,4),%xmm2
addss  %xmm2,%xmm1
jmp    11e0 <cpu_gemm_nt+0xe0>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @cpu_gemm_nt(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
%30 = alloca float
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 %31
31: ; preds = %87, %13
%32 = load i32, i32* %27
%33 = load i32, i32* %16
%34 = icmp slt i32 %32, %33
br i1 %34, label %35, label %90
35: ; preds = %31
store i32 0, i32* %28
br label %36
36: ; preds = %83, %35
%37 = load i32, i32* %28
%38 = load i32, i32* %17
%39 = icmp slt i32 %37, %38
br i1 %39, label %40, label %86
40: ; preds = %36
store float 0.000000e+00, float* %30
store i32 0, i32* %29
br label %41
41: ; preds = %68, %40
%42 = load i32, i32* %29
%43 = load i32, i32* %18
%44 = icmp slt i32 %42, %43
br i1 %44, label %45, label %71
45: ; preds = %41
%46 = load float, float* %19
%47 = load float*, float** %20
%48 = load i32, i32* %27
%49 = load i32, i32* %21
%50 = mul nsw i32 %48, %49
%51 = load i32, i32* %29
%52 = add nsw i32 %50, %51
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds float, float* %47, i64 %53
%55 = load float, float* %54
%56 = fmul float %46, %55
%57 = load float*, float** %22
%58 = load i32, i32* %29
%59 = load i32, i32* %28
%60 = load i32, i32* %23
%61 = mul nsw i32 %59, %60
%62 = add nsw i32 %58, %61
%63 = sext i32 %62 to i64
%64 = getelementptr inbounds float, float* %57, i64 %63
%65 = load float, float* %64
%66 = load float, float* %30
%67 = call float @llvm.fmuladd.f32(float %56, float %65, float %66)
store float %67, float* %30
br label %68
68: ; preds = %45
%69 = load i32, i32* %29
%70 = add nsw i32 %69, 1
store i32 %70, i32* %29
br label %41
71: ; preds = %41
%72 = load float, float* %30
%73 = load float*, float** %25
%74 = load i32, i32* %27
%75 = load i32, i32* %26
%76 = mul nsw i32 %74, %75
%77 = load i32, i32* %28
%78 = add nsw i32 %76, %77
%79 = sext i32 %78 to i64
%80 = getelementptr inbounds float, float* %73, i64 %79
%81 = load float, float* %80
%82 = fadd float %81, %72
store float %82, float* %80
br label %83
83: ; preds = %71
%84 = load i32, i32* %28
%85 = add nsw i32 %84, 1
store i32 %85, i32* %28
br label %36
86: ; preds = %36
br label %87
87: ; preds = %86
%88 = load i32, i32* %27
%89 = add nsw i32 %88, 1
store i32 %89, i32* %27
br label %31
90: ; preds = %31
ret void
}

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