void copy_tile(float *src, int nc, int nr, int nch, float *dst, int x0, int y0,
               int w, int h, int dst_nch) {
  for (int j = 0; j < h; j++) {
    for (int i = 0; i < w; i++) {
      for (int c = 0; c < dst_nch; c++) {
        float v = 0;
        int ii = x0 + i;
        int jj = y0 + j;
        if (ii >= 0 && jj >= 0 && ii < nc && jj < nr && c < nch) {
          v = src[nch * (ii + jj * nc) + c];
        }
        dst[dst_nch * (i + j * w) + c] = v;
      }
    }
  }
}


x86 assembly (clang, -O0):
<copy_tile>:
push   %rbp
mov    %rsp,%rbp
mov    0x28(%rbp),%eax
mov    0x20(%rbp),%eax
mov    0x18(%rbp),%eax
mov    0x10(%rbp),%eax
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %ecx,-0x14(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9d,-0x24(%rbp)
movl   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    0x20(%rbp),%eax
jge    1230 <copy_tile+0x130>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    0x18(%rbp),%eax
jge    121d <copy_tile+0x11d>
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    0x28(%rbp),%eax
jge    120a <copy_tile+0x10a>
xorps  %xmm0,%xmm0
movss  %xmm0,-0x34(%rbp)
mov    -0x24(%rbp),%eax
add    -0x2c(%rbp),%eax
mov    %eax,-0x38(%rbp)
mov    0x10(%rbp),%eax
add    -0x28(%rbp),%eax
mov    %eax,-0x3c(%rbp)
cmpl   $0x0,-0x38(%rbp)
jl     11d6 <copy_tile+0xd6>
cmpl   $0x0,-0x3c(%rbp)
jl     11d6 <copy_tile+0xd6>
mov    -0x38(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    11d6 <copy_tile+0xd6>
mov    -0x3c(%rbp),%eax
cmp    -0x10(%rbp),%eax
jge    11d6 <copy_tile+0xd6>
mov    -0x30(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11d6 <copy_tile+0xd6>
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
mov    -0x38(%rbp),%edx
mov    -0x3c(%rbp),%esi
imul   -0xc(%rbp),%esi
add    %esi,%edx
imul   %edx,%ecx
add    -0x30(%rbp),%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm0
movss  %xmm0,-0x34(%rbp)
movss  -0x34(%rbp),%xmm0
mov    -0x20(%rbp),%rax
mov    0x28(%rbp),%ecx
mov    -0x2c(%rbp),%edx
mov    -0x28(%rbp),%esi
imul   0x18(%rbp),%esi
add    %esi,%edx
imul   %edx,%ecx
add    -0x30(%rbp),%ecx
movslq %ecx,%rcx
movss  %xmm0,(%rax,%rcx,4)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1152 <copy_tile+0x52>
jmp    120f <copy_tile+0x10f>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    113f <copy_tile+0x3f>
jmp    1222 <copy_tile+0x122>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    112c <copy_tile+0x2c>
pop    %rbp
ret

x86 assembly (clang, -O2):
<copy_tile>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x10,%rsp
mov    %r8,-0x60(%rsp)
mov    %rdi,-0x68(%rsp)
mov    0x58(%rsp),%ebx
test   %ebx,%ebx
jle    1390 <copy_tile+0x290>
mov    0x60(%rsp),%eax
movslq %ecx,%rcx
movslq %r9d,%r8
movslq %esi,%rdi
movslq %eax,%rbp
movslq 0x48(%rsp),%rsi
movslq %edx,%rdx
mov    %rdx,-0x8(%rsp)
mov    %eax,%edx
movslq 0x50(%rsp),%r9
mov    %ebx,%eax
mov    %rax,-0x30(%rsp)
mov    %ebp,%ebx
mov    %rbx,-0x10(%rsp)
and    $0xfffffffe,%ebx
mov    %rsi,%rax
mov    %rsi,-0x48(%rsp)
imul   %rdi,%rsi
mov    %r8,%rax
mov    %r8,(%rsp)
add    %r8,%rsi
imul   %rcx,%rsi
mov    -0x68(%rsp),%rax
lea    (%rax,%rsi,4),%rax
add    $0x4,%rax
mov    %rax,-0x70(%rsp)
mov    %rcx,%rax
mov    %rdi,-0x58(%rsp)
imul   %rdi,%rax
shl    $0x2,%rax
mov    %rax,-0x38(%rsp)
mov    %rbp,%rax
imul   %r9,%rax
shl    $0x2,%rax
mov    %rax,-0x40(%rsp)
mov    %r9,-0x50(%rsp)
mov    %r9d,%eax
mov    %rax,0x8(%rsp)
lea    0x0(,%rcx,4),%r12
mov    -0x60(%rsp),%rax
add    $0x4,%rax
mov    %rax,-0x78(%rsp)
mov    %rbp,-0x20(%rsp)
lea    0x0(,%rbp,4),%r14
xor    %eax,%eax
mov    %rax,-0x80(%rsp)
jmp    1225 <copy_tile+0x125>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mov    -0x80(%rsp),%rsi
add    $0x1,%rsi
mov    -0x38(%rsp),%rax
add    %rax,-0x70(%rsp)
mov    -0x78(%rsp),%rax
add    -0x40(%rsp),%rax
mov    %rax,-0x78(%rsp)
mov    %rsi,%rax
mov    %rsi,-0x80(%rsp)
cmp    -0x30(%rsp),%rsi
je     1390 <copy_tile+0x290>
cmpl   $0x0,0x50(%rsp)
jle    11f0 <copy_tile+0xf0>
mov    -0x48(%rsp),%rax
mov    -0x80(%rsp),%rsi
lea    (%rsi,%rax,1),%r15
mov    %r15,%rax
imul   -0x58(%rsp),%rax
mov    %rax,-0x28(%rsp)
imul   -0x50(%rsp),%rsi
mov    %rsi,-0x18(%rsp)
mov    -0x78(%rsp),%r10
mov    -0x70(%rsp),%rbp
xor    %r8d,%r8d
jmp    1293 <copy_tile+0x193>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
add    %rsi,%r9
mov    -0x60(%rsp),%rax
movss  %xmm0,(%rax,%r9,4)
add    $0x1,%r8
add    %r12,%rbp
add    %r14,%r10
cmp    0x8(%rsp),%r8
je     11f0 <copy_tile+0xf0>
test   %edx,%edx
jle    127e <copy_tile+0x17e>
cmp    -0x8(%rsp),%r15
mov    %edx,%edi
setl   %dl
mov    (%rsp),%rax
lea    (%r8,%rax,1),%r11
mov    %r11,%rsi
or     %r15,%rsi
setns  %al
cmp    -0x58(%rsp),%r11
setl   %r13b
and    %al,%r13b
and    %dl,%r13b
mov    %edi,%edx
cmp    $0x1,%edi
jne    12e0 <copy_tile+0x1e0>
xor    %r9d,%r9d
testb  $0x1,-0x10(%rsp)
je     127e <copy_tile+0x17e>
jmp    134f <copy_tile+0x24f>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
xor    %esi,%esi
jmp    12ff <copy_tile+0x1ff>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movss  %xmm0,(%r10,%r9,4)
add    $0x1,%rsi
cmp    %rbx,%rsi
je     1340 <copy_tile+0x240>
mov    %rsi,%r9
cmp    %rcx,%rsi
setl   %al
and    %r13b,%al
xorps  %xmm0,%xmm0
xorps  %xmm1,%xmm1
cmp    $0x1,%al
jne    131c <copy_tile+0x21c>
movss  -0x4(%rbp,%r9,4),%xmm1
movss  %xmm1,-0x4(%r10,%r9,4)
lea    0x1(%r9),%rsi
cmp    %rcx,%rsi
setl   %al
and    %r13b,%al
cmp    $0x1,%al
jne    12f0 <copy_tile+0x1f0>
movss  0x0(%rbp,%r9,4),%xmm0
jmp    12f0 <copy_tile+0x1f0>
nopl   (%rax)
add    $0x2,%r9
testb  $0x1,-0x10(%rsp)
je     127e <copy_tile+0x17e>
mov    -0x18(%rsp),%rax
lea    (%r8,%rax,1),%rsi
imul   -0x20(%rsp),%rsi
cmp    %rcx,%r9
setl   %al
and    %al,%r13b
xorps  %xmm0,%xmm0
cmp    $0x1,%r13b
jne    1270 <copy_tile+0x170>
add    -0x28(%rsp),%r11
imul   %rcx,%r11
add    %r9,%r11
mov    -0x68(%rsp),%rax
movss  (%rax,%r11,4),%xmm0
jmp    1270 <copy_tile+0x170>
add    $0x10,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

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