// File: yuang-chen[P]paraGCN/src/module.cpp
// Function: Matmul::backward()
void Matmul::backward() {
    x->zero_grad();
    y->zero_grad();
#pragma omp parallel for schedule(static)
    for(int i =0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            float tmp = 0;
#ifdef SIMD
#pragma omp simd reduction(+:tmp)
#endif
            for(int k = 0; k < l; k++) {
                tmp += z->grad[i * l + k] * y->data[j * l + k];
#ifdef OMP
                b->local_grad[omp_get_thread_num()][j * l + k] += z->grad[i * l + k] * y->data[j * l + k];
#else 
                y->grad[j * l + k] += z->grad[i * l + k] * x->data[i * n + j];
#endif
            }
            x->grad[i * n + j] = tmp;
        }
#ifdef OMP
#ifdef SIMD
#pragma omp parallel for simd schedule(static)
#else
#pragma omp parallel for schedule(static)
#endif
        for(int i = 0; i < b->grad.size();i++) {
            for(int thread = 0; thread < omp_get_num_threads(); thread++) {
                b->grad[i] += b->local_grad[thread][i];
            }
        }
#endif
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x20(%rbp)
movq 0x8(%rax), %rdi
callq 0xcff0
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xcff0
movl $0x0, -0xc(%rbp)
movq -0x20(%rbp), %rcx
movl -0xc(%rbp), %eax
cmpl 0x20(%rcx), %eax
jge 0xba12
movl $0x0, -0x10(%rbp)
movq -0x20(%rbp), %rcx
movl -0x10(%rbp), %eax
cmpl 0x24(%rcx), %eax
jge 0xba02
xorps %xmm0, %xmm0
movss %xmm0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movq -0x20(%rbp), %rcx
movl -0x18(%rbp), %eax
cmpl 0x28(%rcx), %eax
jge 0xb9c3
movq -0x20(%rbp), %rcx
movq 0x18(%rcx), %rdi
addq $0x18, %rdi
movl -0xc(%rbp), %eax
imull 0x28(%rcx), %eax
addl -0x18(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movq -0x20(%rbp), %rcx
movss (%rax), %xmm0
movss %xmm0, -0x2c(%rbp)
movq 0x10(%rcx), %rdi
movl -0x10(%rbp), %eax
imull 0x28(%rcx), %eax
addl -0x18(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movss -0x2c(%rbp), %xmm0
movq -0x20(%rbp), %rcx
movss (%rax), %xmm2
movss -0x14(%rbp), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x14(%rbp)
movq 0x18(%rcx), %rdi
addq $0x18, %rdi
movl -0xc(%rbp), %eax
imull 0x28(%rcx), %eax
addl -0x18(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movq -0x20(%rbp), %rcx
movss (%rax), %xmm0
movss %xmm0, -0x28(%rbp)
movq 0x8(%rcx), %rdi
movl -0xc(%rbp), %eax
imull 0x24(%rcx), %eax
addl -0x10(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movq -0x20(%rbp), %rcx
movss (%rax), %xmm0
movss %xmm0, -0x24(%rbp)
movq 0x10(%rcx), %rdi
addq $0x18, %rdi
movl -0x10(%rbp), %eax
imull 0x28(%rcx), %eax
addl -0x18(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movss -0x28(%rbp), %xmm0
movss -0x24(%rbp), %xmm2
movss (%rax), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, (%rax)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xb8c7
movq -0x20(%rbp), %rcx
movss -0x14(%rbp), %xmm0
movss %xmm0, -0x30(%rbp)
movq 0x8(%rcx), %rdi
addq $0x18, %rdi
movl -0xc(%rbp), %eax
imull 0x24(%rcx), %eax
addl -0x10(%rbp), %eax
movslq %eax, %rsi
callq 0x5520
movss -0x30(%rbp), %xmm0
movss %xmm0, (%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0xb8a8
jmp 0xba04
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0xb891
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax,%rax)