#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 */
float sqrtf(float);
void neuralops_batchnorm2d_bwd_mean(size_t batch_sz, size_t width,
                                    size_t height, size_t chan,
                                    const float *in_buf, const float *mean,
                                    const float *var, const float *var_grad,
                                    const float *out_grad, float *mean_grad,
                                    float epsilon) {
  for (size_t a = 0; a < chan; a += 1) {
    mean_grad[a] = 0.0f;
  }
  size_t p = 0;
  for (size_t idx = 0; idx < batch_sz; idx += 1) {
    for (size_t a = 0; a < chan; a += 1) {
      float m = mean[a];
      float v = var[a];
      float rs = -1.0f / sqrtf(v + epsilon);
      float dv = var_grad[a];
      float c = -2.0f / ((float)(width * height * batch_sz - 1));
      for (size_t y = 0; y < height; y += 1) {
        for (size_t x = 0; x < width; x += 1) {
          mean_grad[a] += out_grad[p] * rs + dv * c * (in_buf[p] - m);
          p += 1;
        }
      }
    }
  }
}


x86 assembly (clang, -O0):
<neuralops_batchnorm2d_bwd_mean>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
mov    0x28(%rbp),%rax
mov    0x20(%rbp),%rax
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%rax
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9,-0x30(%rbp)
movss  %xmm0,-0x34(%rbp)
movq   $0x0,-0x40(%rbp)
mov    -0x40(%rbp),%rax
cmp    -0x20(%rbp),%rax
jae    117f <neuralops_batchnorm2d_bwd_mean+0x6f>
mov    0x28(%rbp),%rax
mov    -0x40(%rbp),%rcx
xorps  %xmm0,%xmm0
movss  %xmm0,(%rax,%rcx,4)
mov    -0x40(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x40(%rbp)
jmp    1150 <neuralops_batchnorm2d_bwd_mean+0x40>
movq   $0x0,-0x48(%rbp)
movq   $0x0,-0x50(%rbp)
mov    -0x50(%rbp),%rax
cmp    -0x8(%rbp),%rax
jae    135d <neuralops_batchnorm2d_bwd_mean+0x24d>
movq   $0x0,-0x58(%rbp)
mov    -0x58(%rbp),%rax
cmp    -0x20(%rbp),%rax
jae    1347 <neuralops_batchnorm2d_bwd_mean+0x237>
mov    -0x30(%rbp),%rax
mov    -0x58(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  %xmm0,-0x5c(%rbp)
mov    0x10(%rbp),%rax
mov    -0x58(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  %xmm0,-0x60(%rbp)
movss  -0x60(%rbp),%xmm0
movss  -0x34(%rbp),%xmm1
addss  %xmm1,%xmm0
call   1030 <sqrtf@plt>
movaps %xmm0,%xmm1
movss  0xe0f(%rip),%xmm0
divss  %xmm1,%xmm0
movss  %xmm0,-0x64(%rbp)
mov    0x18(%rbp),%rax
mov    -0x58(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%rcx
imul   %rcx,%rax
mov    -0x8(%rbp),%rcx
imul   %rcx,%rax
add    $0xffffffffffffffff,%rax
mov    %rax,%rdx
shr    %rdx
mov    %eax,%ecx
and    $0x1,%ecx
or     %rdx,%rcx
cvtsi2ss %rcx,%xmm0
addss  %xmm0,%xmm0
cvtsi2ss %rax,%xmm1
movss  %xmm1,-0x88(%rbp)
ff
test   %rax,%rax
movss  %xmm0,-0x84(%rbp)
ff
js     126d <neuralops_batchnorm2d_bwd_mean+0x15d>
movss  -0x88(%rbp),%xmm0
ff
movss  %xmm0,-0x84(%rbp)
ff
movss  -0x84(%rbp),%xmm1
ff
movss  0xd83(%rip),%xmm0
divss  %xmm1,%xmm0
movss  %xmm0,-0x6c(%rbp)
movq   $0x0,-0x78(%rbp)
mov    -0x78(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    1331 <neuralops_batchnorm2d_bwd_mean+0x221>
movq   $0x0,-0x80(%rbp)
mov    -0x80(%rbp),%rax
cmp    -0x10(%rbp),%rax
jae    131b <neuralops_batchnorm2d_bwd_mean+0x20b>
mov    0x20(%rbp),%rax
mov    -0x48(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  -0x64(%rbp),%xmm2
movss  -0x68(%rbp),%xmm1
mulss  -0x6c(%rbp),%xmm1
mov    -0x28(%rbp),%rax
mov    -0x48(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm3
subss  -0x5c(%rbp),%xmm3
mulss  %xmm3,%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    0x28(%rbp),%rax
mov    -0x58(%rbp),%rcx
addss  (%rax,%rcx,4),%xmm0
movss  %xmm0,(%rax,%rcx,4)
mov    -0x48(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x48(%rbp)
mov    -0x80(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x80(%rbp)
jmp    12a4 <neuralops_batchnorm2d_bwd_mean+0x194>
jmp    1320 <neuralops_batchnorm2d_bwd_mean+0x210>
mov    -0x78(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x78(%rbp)
jmp    128e <neuralops_batchnorm2d_bwd_mean+0x17e>
jmp    1336 <neuralops_batchnorm2d_bwd_mean+0x226>
mov    -0x58(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x58(%rbp)
jmp    11a5 <neuralops_batchnorm2d_bwd_mean+0x95>
jmp    134c <neuralops_batchnorm2d_bwd_mean+0x23c>
mov    -0x50(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x50(%rbp)
jmp    118f <neuralops_batchnorm2d_bwd_mean+0x7f>
add    $0x90,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<neuralops_batchnorm2d_bwd_mean>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x48,%rsp
movss  %xmm0,0x1c(%rsp)
mov    %r9,0x40(%rsp)
mov    %r8,%rbx
mov    %rsi,%r13
mov    %rdi,0x8(%rsp)
mov    0x98(%rsp),%rbp
test   %rcx,%rcx
mov    %rcx,0x28(%rsp)
mov    %rdx,0x20(%rsp)
je     1177 <neuralops_batchnorm2d_bwd_mean+0x57>
lea    0x0(,%rcx,4),%rdx
mov    %rbp,%rdi
xor    %esi,%esi
call   1030 <memset@plt>
mov    0x20(%rsp),%rdx
mov    0x28(%rsp),%rcx
cmpq   $0x0,0x8(%rsp)
je     1374 <neuralops_batchnorm2d_bwd_mean+0x254>
mov    %r13,%rax
imul   0x8(%rsp),%rax
imul   %rdx,%rax
add    $0xffffffffffffffff,%rax
js     11a0 <neuralops_batchnorm2d_bwd_mean+0x80>
xorps  %xmm0,%xmm0
cvtsi2ss %rax,%xmm0
jmp    11b8 <neuralops_batchnorm2d_bwd_mean+0x98>
mov    %rax,%rsi
shr    %rsi
and    $0x1,%eax
or     %rsi,%rax
xorps  %xmm0,%xmm0
cvtsi2ss %rax,%xmm0
addss  %xmm0,%xmm0
mov    0x90(%rsp),%r14
mov    0x80(%rsp),%rdi
movss  0xe30(%rip),%xmm1
divss  %xmm0,%xmm1
movss  %xmm1,0x14(%rsp)
mov    %r13,%r8
and    $0xfffffffffffffffe,%r8
xor    %r15d,%r15d
xorps  %xmm5,%xmm5
xor    %eax,%eax
mov    %r8,0x38(%rsp)
jmp    1204 <neuralops_batchnorm2d_bwd_mean+0xe4>
mov    0x30(%rsp),%rax
add    $0x1,%rax
cmp    0x8(%rsp),%rax
je     1374 <neuralops_batchnorm2d_bwd_mean+0x254>
test   %rcx,%rcx
mov    %rax,0x30(%rsp)
je     11f0 <neuralops_batchnorm2d_bwd_mean+0xd0>
xor    %r12d,%r12d
jmp    1229 <neuralops_batchnorm2d_bwd_mean+0x109>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
add    $0x1,%r12
cmp    %rcx,%r12
je     11f0 <neuralops_batchnorm2d_bwd_mean+0xd0>
mov    0x40(%rsp),%rax
movss  (%rax,%r12,4),%xmm6
movss  (%rdi,%r12,4),%xmm0
addss  0x1c(%rsp),%xmm0
ucomiss %xmm5,%xmm0
jb     1250 <neuralops_batchnorm2d_bwd_mean+0x130>
sqrtss %xmm0,%xmm0
test   %rdx,%rdx
jne    1280 <neuralops_batchnorm2d_bwd_mean+0x160>
jmp    1220 <neuralops_batchnorm2d_bwd_mean+0x100>
movss  %xmm6,0x18(%rsp)
call   1040 <sqrtf@plt>
movss  0x18(%rsp),%xmm6
xorps  %xmm5,%xmm5
mov    0x38(%rsp),%r8
mov    0x80(%rsp),%rdi
mov    0x20(%rsp),%rdx
mov    0x28(%rsp),%rcx
test   %rdx,%rdx
je     1220 <neuralops_batchnorm2d_bwd_mean+0x100>
movss  0xd7c(%rip),%xmm1
divss  %xmm0,%xmm1
mov    0x88(%rsp),%rax
movss  (%rax,%r12,4),%xmm0
mulss  0x14(%rsp),%xmm0
xor    %eax,%eax
jmp    12bd <neuralops_batchnorm2d_bwd_mean+0x19d>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
add    $0x1,%rax
cmp    %rdx,%rax
je     1220 <neuralops_batchnorm2d_bwd_mean+0x100>
test   %r13,%r13
je     12b0 <neuralops_batchnorm2d_bwd_mean+0x190>
movss  0x0(%rbp,%r12,4),%xmm2
mov    %r8,%rsi
cmp    $0x1,%r13
je     133a <neuralops_batchnorm2d_bwd_mean+0x21a>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movss  (%rbx,%r15,4),%xmm3
subss  %xmm6,%xmm3
mulss  %xmm0,%xmm3
movss  (%r14,%r15,4),%xmm4
mulss  %xmm1,%xmm4
addss  %xmm3,%xmm4
addss  %xmm2,%xmm4
movss  %xmm4,0x0(%rbp,%r12,4)
movss  0x4(%rbx,%r15,4),%xmm3
subss  %xmm6,%xmm3
mulss  %xmm0,%xmm3
movss  0x4(%r14,%r15,4),%xmm2
mulss  %xmm1,%xmm2
addss  %xmm3,%xmm2
addss  %xmm4,%xmm2
movss  %xmm2,0x0(%rbp,%r12,4)
add    $0x2,%r15
add    $0xfffffffffffffffe,%rsi
jne    12e0 <neuralops_batchnorm2d_bwd_mean+0x1c0>
test   $0x1,%r13b
je     12b0 <neuralops_batchnorm2d_bwd_mean+0x190>
movss  (%rbx,%r15,4),%xmm3
subss  %xmm6,%xmm3
mulss  %xmm0,%xmm3
movss  (%r14,%r15,4),%xmm4
mulss  %xmm1,%xmm4
addss  %xmm3,%xmm4
addss  %xmm4,%xmm2
movss  %xmm2,0x0(%rbp,%r12,4)
add    $0x1,%r15
jmp    12b0 <neuralops_batchnorm2d_bwd_mean+0x190>
add    $0x48,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @neuralops_batchnorm2d_bwd_mean(i64 %0, i64 %1, i64 %2, i64 %3, float* %4, float* %5, float* %6, float* %7, float* %8, float* %9, float %10) {
%12 = alloca i64
%13 = alloca i64
%14 = alloca i64
%15 = alloca i64
%16 = alloca float*
%17 = alloca float*
%18 = alloca float*
%19 = alloca float*
%20 = alloca float*
%21 = alloca float*
%22 = alloca float
%23 = alloca i64
%24 = alloca i64
%25 = alloca i64
%26 = alloca i64
%27 = alloca float
%28 = alloca float
%29 = alloca float
%30 = alloca float
%31 = alloca float
%32 = alloca i64
%33 = alloca i64
store i64 %0, i64* %12
store i64 %1, i64* %13
store i64 %2, i64* %14
store i64 %3, i64* %15
store float* %4, float** %16
store float* %5, float** %17
store float* %6, float** %18
store float* %7, float** %19
store float* %8, float** %20
store float* %9, float** %21
store float %10, float* %22
store i64 0, i64* %23
br label %34
34: ; preds = %42, %11
%35 = load i64, i64* %23
%36 = load i64, i64* %15
%37 = icmp ult i64 %35, %36
br i1 %37, label %38, label %45
38: ; preds = %34
%39 = load float*, float** %21
%40 = load i64, i64* %23
%41 = getelementptr inbounds float, float* %39, i64 %40
store float 0.000000e+00, float* %41
br label %42
42: ; preds = %38
%43 = load i64, i64* %23
%44 = add i64 %43, 1
store i64 %44, i64* %23
br label %34
45: ; preds = %34
store i64 0, i64* %24
store i64 0, i64* %25
br label %46
46: ; preds = %126, %45
%47 = load i64, i64* %25
%48 = load i64, i64* %12
%49 = icmp ult i64 %47, %48
br i1 %49, label %50, label %129
50: ; preds = %46
store i64 0, i64* %26
br label %51
51: ; preds = %122, %50
%52 = load i64, i64* %26
%53 = load i64, i64* %15
%54 = icmp ult i64 %52, %53
br i1 %54, label %55, label %125
55: ; preds = %51
%56 = load float*, float** %17
%57 = load i64, i64* %26
%58 = getelementptr inbounds float, float* %56, i64 %57
%59 = load float, float* %58
store float %59, float* %27
%60 = load float*, float** %18
%61 = load i64, i64* %26
%62 = getelementptr inbounds float, float* %60, i64 %61
%63 = load float, float* %62
store float %63, float* %28
%64 = load float, float* %28
%65 = load float, float* %22
%66 = fadd float %64, %65
%67 = call float @sqrtf(float %66)
%68 = fdiv float -1.000000e+00, %67
store float %68, float* %29
%69 = load float*, float** %19
%70 = load i64, i64* %26
%71 = getelementptr inbounds float, float* %69, i64 %70
%72 = load float, float* %71
store float %72, float* %30
%73 = load i64, i64* %13
%74 = load i64, i64* %14
%75 = mul i64 %73, %74
%76 = load i64, i64* %12
%77 = mul i64 %75, %76
%78 = sub i64 %77, 1
%79 = uitofp i64 %78 to float
%80 = fdiv float -2.000000e+00, %79
store float %80, float* %31
store i64 0, i64* %32
br label %81
81: ; preds = %118, %55
%82 = load i64, i64* %32
%83 = load i64, i64* %14
%84 = icmp ult i64 %82, %83
br i1 %84, label %85, label %121
85: ; preds = %81
store i64 0, i64* %33
br label %86
86: ; preds = %114, %85
%87 = load i64, i64* %33
%88 = load i64, i64* %13
%89 = icmp ult i64 %87, %88
br i1 %89, label %90, label %117
90: ; preds = %86
%91 = load float*, float** %20
%92 = load i64, i64* %24
%93 = getelementptr inbounds float, float* %91, i64 %92
%94 = load float, float* %93
%95 = load float, float* %29
%96 = load float, float* %30
%97 = load float, float* %31
%98 = fmul float %96, %97
%99 = load float*, float** %16
%100 = load i64, i64* %24
%101 = getelementptr inbounds float, float* %99, i64 %100
%102 = load float, float* %101
%103 = load float, float* %27
%104 = fsub float %102, %103
%105 = fmul float %98, %104
%106 = call float @llvm.fmuladd.f32(float %94, float %95, float %105)
%107 = load float*, float** %21
%108 = load i64, i64* %26
%109 = getelementptr inbounds float, float* %107, i64 %108
%110 = load float, float* %109
%111 = fadd float %110, %106
store float %111, float* %109
%112 = load i64, i64* %24
%113 = add i64 %112, 1
store i64 %113, i64* %24
br label %114
114: ; preds = %90
%115 = load i64, i64* %33
%116 = add i64 %115, 1
store i64 %116, i64* %33
br label %86
117: ; preds = %86
br label %118
118: ; preds = %117
%119 = load i64, i64* %32
%120 = add i64 %119, 1
store i64 %120, i64* %32
br label %81
121: ; preds = %81
br label %122
122: ; preds = %121
%123 = load i64, i64* %26
%124 = add i64 %123, 1
store i64 %124, i64* %26
br label %51
125: ; preds = %51
br label %126
126: ; preds = %125
%127 = load i64, i64* %25
%128 = add i64 %127, 1
store i64 %128, i64* %25
br label %46
129: ; preds = %46
ret void
}

LLVM IR (-O2):
define void @neuralops_batchnorm2d_bwd_mean(i64 %0, i64 %1, i64 %2, i64 %3, float* nocapture %4, float* nocapture %5, float* nocapture %6, float* nocapture %7, float* nocapture %8, float* nocapture %9, float %10) {
%12 = icmp eq i64 %3, 0
br i1 %12, label %16, label %13
13: ; preds = %11
%14 = bitcast float* %9 to i8*
%15 = shl nuw i64 %3, 2
br label %16
16: ; preds = %13, %11
%17 = icmp eq i64 %0, 0
br i1 %17, label %33, label %18
18: ; preds = %16
%19 = mul i64 %1, %0
%20 = mul i64 %19, %2
%21 = add i64 %20, -1
%22 = uitofp i64 %21 to float
%23 = fdiv float -2.000000e+00, %22
%24 = icmp eq i64 %2, 0
%25 = icmp eq i64 %1, 0
%26 = and i64 %1, 1
%27 = icmp eq i64 %1, 1
%28 = and i64 %1, -2
%29 = icmp eq i64 %26, 0
br label %30
30: ; preds = %18, %34
%31 = phi i64 [ 0, %18 ], [ %35, %34 ]
%32 = phi i64 [ 0, %18 ], [ %36, %34 ]
br i1 %12, label %34, label %38
33: ; preds = %34, %16
ret void
34: ; preds = %58, %30
%35 = phi i64 [ %31, %30 ], [ %59, %58 ]
%36 = add nuw i64 %32, 1
%37 = icmp eq i64 %36, %0
br i1 %37, label %33, label %30
38: ; preds = %30, %58
%39 = phi i64 [ %59, %58 ], [ %31, %30 ]
%40 = phi i64 [ %60, %58 ], [ 0, %30 ]
%41 = getelementptr inbounds float, float* %5, i64 %40
%42 = load float, float* %41
%43 = getelementptr inbounds float, float* %6, i64 %40
%44 = load float, float* %43
%45 = fadd float %44, %10
%46 = tail call float @sqrtf(float %45)
%47 = fdiv float -1.000000e+00, %46
br i1 %24, label %58, label %48
48: ; preds = %38
%49 = getelementptr inbounds float, float* %7, i64 %40
%50 = load float, float* %49
%51 = fmul float %23, %50
%52 = getelementptr inbounds float, float* %9, i64 %40
br label %53
53: ; preds = %48, %76
%54 = phi i64 [ 0, %48 ], [ %78, %76 ]
%55 = phi i64 [ %39, %48 ], [ %77, %76 ]
br i1 %25, label %76, label %56
56: ; preds = %53
%57 = load float, float* %52
br i1 %27, label %62, label %80
58: ; preds = %76, %38
%59 = phi i64 [ %39, %38 ], [ %77, %76 ]
%60 = add nuw i64 %40, 1
%61 = icmp eq i64 %60, %3
br i1 %61, label %34, label %38
62: ; preds = %80, %56
%63 = phi i64 [ undef, %56 ], [ %101, %80 ]
%64 = phi float [ %57, %56 ], [ %100, %80 ]
%65 = phi i64 [ %55, %56 ], [ %101, %80 ]
br i1 %29, label %76, label %66
66: ; preds = %62
%67 = getelementptr inbounds float, float* %8, i64 %65
%68 = load float, float* %67
%69 = getelementptr inbounds float, float* %4, i64 %65
%70 = load float, float* %69
%71 = fsub float %70, %42
%72 = fmul float %51, %71
%73 = tail call float @llvm.fmuladd.f32(float %68, float %47, float %72)
%74 = fadd float %64, %73
store float %74, float* %52
%75 = add i64 %65, 1
br label %76
76: ; preds = %66, %62, %53
%77 = phi i64 [ %55, %53 ], [ %63, %62 ], [ %75, %66 ]
%78 = add nuw i64 %54, 1
%79 = icmp eq i64 %78, %2
br i1 %79, label %58, label %53
80: ; preds = %56, %80
%81 = phi float [ %100, %80 ], [ %57, %56 ]
%82 = phi i64 [ %101, %80 ], [ %55, %56 ]
%83 = phi i64 [ %102, %80 ], [ 0, %56 ]
%84 = getelementptr inbounds float, float* %8, i64 %82
%85 = load float, float* %84
%86 = getelementptr inbounds float, float* %4, i64 %82
%87 = load float, float* %86
%88 = fsub float %87, %42
%89 = fmul float %51, %88
%90 = tail call float @llvm.fmuladd.f32(float %85, float %47, float %89)
%91 = fadd float %81, %90
store float %91, float* %52
%92 = add i64 %82, 1
%93 = getelementptr inbounds float, float* %8, i64 %92
%94 = load float, float* %93
%95 = getelementptr inbounds float, float* %4, i64 %92
%96 = load float, float* %95
%97 = fsub float %96, %42
%98 = fmul float %51, %97
%99 = tail call float @llvm.fmuladd.f32(float %94, float %47, float %98)
%100 = fadd float %91, %99
store float %100, float* %52
%101 = add i64 %82, 2
%102 = add i64 %83, 2
%103 = icmp eq i64 %102, %28
br i1 %103, label %62, label %80
}