void apply_convolution(unsigned char image[][1000],
                       unsigned char convoluted_image[][1000],
                       signed char convolution[][3], long image_size) {
  long i, j, k, m, temp;
  for (i = 1; i < (image_size - 1); i++)
    for (j = 1; j < (image_size - 1); j++) {
      temp = 0;
      for (k = 0; k < 3; k++)
        for (m = 0; m < 3; m++) {
          temp += (image[i + k - 1][j + m - 1]) * (convolution[k][m]);
        }
      if (temp > 255)
        temp = 255;
      if (temp < 0)
        temp = 0;
      convoluted_image[i][j] = temp;
    }
}


x86 assembly (clang, -O0):
<apply_convolution>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
movq   $0x1,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    -0x20(%rbp),%rcx
sub    $0x1,%rcx
cmp    %rcx,%rax
jge    125a <apply_convolution+0x15a>
movq   $0x1,-0x30(%rbp)
mov    -0x30(%rbp),%rax
mov    -0x20(%rbp),%rcx
sub    $0x1,%rcx
cmp    %rcx,%rax
jge    1244 <apply_convolution+0x144>
movq   $0x0,-0x48(%rbp)
movq   $0x0,-0x38(%rbp)
cmpq   $0x3,-0x38(%rbp)
jge    11ee <apply_convolution+0xee>
movq   $0x0,-0x40(%rbp)
cmpq   $0x3,-0x40(%rbp)
jge    11d8 <apply_convolution+0xd8>
mov    -0x8(%rbp),%rax
mov    -0x28(%rbp),%rcx
add    -0x38(%rbp),%rcx
sub    $0x1,%rcx
imul   $0x3e8,%rcx,%rcx
add    %rcx,%rax
mov    -0x30(%rbp),%rcx
add    -0x40(%rbp),%rcx
sub    $0x1,%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x18(%rbp),%rcx
imul   $0x3,-0x38(%rbp),%rdx
add    %rdx,%rcx
mov    -0x40(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
imul   %ecx,%eax
cltq
add    -0x48(%rbp),%rax
mov    %rax,-0x48(%rbp)
mov    -0x40(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x40(%rbp)
jmp    1171 <apply_convolution+0x71>
jmp    11dd <apply_convolution+0xdd>
mov    -0x38(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x38(%rbp)
jmp    115e <apply_convolution+0x5e>
cmpq   $0xff,-0x48(%rbp)
jle    1204 <apply_convolution+0x104>
movq   $0xff,-0x48(%rbp)
cmpq   $0x0,-0x48(%rbp)
jge    1217 <apply_convolution+0x117>
movq   $0x0,-0x48(%rbp)
mov    -0x48(%rbp),%rax
mov    %al,%dl
mov    -0x10(%rbp),%rax
imul   $0x3e8,-0x28(%rbp),%rcx
add    %rcx,%rax
mov    -0x30(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x30(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x30(%rbp)
jmp    1139 <apply_convolution+0x39>
jmp    1249 <apply_convolution+0x149>
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    111c <apply_convolution+0x1c>
pop    %rbp
ret

x86 assembly (clang, -O2):
<apply_convolution>:
push   %rbx
cmp    $0x3,%rcx
jl     1229 <apply_convolution+0x129>
lea    -0x1(%rcx),%r8
add    $0x7d2,%rdi
add    $0xfffffffffffffffe,%rcx
add    $0x3e9,%rsi
mov    $0x1,%r9d
jmp    114b <apply_convolution+0x4b>
nopl   0x0(%rax)
add    $0x1,%r9
add    $0x3e8,%rdi
add    $0x3e8,%rsi
cmp    %r8,%r9
je     1229 <apply_convolution+0x129>
xor    %r10d,%r10d
jmp    115d <apply_convolution+0x5d>
mov    %al,(%rsi,%r10,1)
add    $0x1,%r10
cmp    %r10,%rcx
je     1130 <apply_convolution+0x30>
movzbl -0x7d2(%rdi,%r10,1),%r11d
ff ff
movsbq (%rdx),%rax
imul   %r11,%rax
movzbl -0x7d1(%rdi,%r10,1),%r11d
ff ff
movsbq 0x1(%rdx),%rbx
imul   %r11,%rbx
add    %rax,%rbx
movzbl -0x7d0(%rdi,%r10,1),%r11d
ff ff
movsbq 0x2(%rdx),%rax
imul   %r11,%rax
add    %rbx,%rax
movzbl -0x3ea(%rdi,%r10,1),%r11d
ff ff
movsbq 0x3(%rdx),%rbx
imul   %r11,%rbx
add    %rax,%rbx
movzbl -0x3e9(%rdi,%r10,1),%r11d
ff ff
movsbq 0x4(%rdx),%rax
imul   %r11,%rax
add    %rbx,%rax
movzbl -0x3e8(%rdi,%r10,1),%r11d
ff ff
movsbq 0x5(%rdx),%rbx
imul   %r11,%rbx
add    %rax,%rbx
movzbl -0x2(%rdi,%r10,1),%r11d
movsbq 0x6(%rdx),%rax
imul   %r11,%rax
add    %rbx,%rax
movzbl -0x1(%rdi,%r10,1),%r11d
movsbq 0x7(%rdx),%rbx
imul   %r11,%rbx
add    %rax,%rbx
movzbl (%rdi,%r10,1),%r11d
movsbq 0x8(%rdx),%rax
imul   %r11,%rax
add    %rbx,%rax
cmp    $0xff,%rax
jl     1219 <apply_convolution+0x119>
mov    $0xff,%eax
test   %rax,%rax
jg     1150 <apply_convolution+0x50>
xor    %eax,%eax
jmp    1150 <apply_convolution+0x50>
pop    %rbx
ret

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

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