int convert_yuv_to_gray0(unsigned char *yuv, unsigned char *gray,
                         unsigned int width, unsigned int height) {
  unsigned int in, out = 0;
  int y0, y1;
  for (in = 0; in < width * height * 2; in += 4) {
    y0 = yuv[in + 0];
    y1 = yuv[in + 2];
    gray[out++] = y0;
    gray[out++] = y1;
  }
  return 0;
}


x86 assembly (clang, -O0):
<convert_yuv_to_gray0>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
movl   $0x0,-0x20(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
imul   -0x18(%rbp),%ecx
shl    $0x1,%ecx
cmp    %ecx,%eax
jae    119b <convert_yuv_to_gray0+0x9b>
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x0,%ecx
mov    %ecx,%ecx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x24(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
mov    %ecx,%ecx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x28(%rbp)
mov    -0x24(%rbp),%eax
mov    %al,%dl
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x20(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x28(%rbp),%eax
mov    %al,%dl
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x20(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0x1c(%rbp)
jmp    1120 <convert_yuv_to_gray0+0x20>
xor    %eax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<convert_yuv_to_gray0>:
push   %rbx
imul   %ecx,%edx
add    %edx,%edx
je     127b <convert_yuv_to_gray0+0x17b>
mov    %edx,%r11d
lea    -0x1(%r11),%rcx
cmp    $0x20,%rcx
jb     1139 <convert_yuv_to_gray0+0x39>
mov    %rcx,%r9
shr    $0x2,%r9
or     $0x3,%rcx
add    %rdi,%rcx
cmp    %rsi,%rcx
jbe    1143 <convert_yuv_to_gray0+0x43>
lea    (%rsi,%r9,2),%rcx
add    $0x2,%rcx
cmp    %rdi,%rcx
jbe    1143 <convert_yuv_to_gray0+0x43>
xor    %r8d,%r8d
xor    %ebx,%ebx
jmp    124f <convert_yuv_to_gray0+0x14f>
lea    0x1(%r9),%rbx
mov    %ebx,%edx
and    $0x7,%edx
test   %rdx,%rdx
mov    $0x8,%r10d
cmovne %rdx,%r10
sub    %r10,%rbx
lea    (%rbx,%rbx,1),%r8
shl    $0x2,%rbx
sub    %r10,%r9
mov    $0xffffffffffffffff,%rdx
xchg   %ax,%ax
movzbl 0x22(%rdi,%rdx,4),%eax
movd   %eax,%xmm0
movzbl 0x20(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
punpcklbw %xmm0,%xmm1
movzbl 0x1e(%rdi,%rdx,4),%eax
movd   %eax,%xmm0
movzbl 0x1c(%rdi,%rdx,4),%eax
movd   %eax,%xmm2
punpcklbw %xmm0,%xmm2
punpcklwd %xmm1,%xmm2
movzbl 0x1a(%rdi,%rdx,4),%eax
movd   %eax,%xmm0
movzbl 0x18(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
punpcklbw %xmm0,%xmm1
movzbl 0x16(%rdi,%rdx,4),%eax
movd   %eax,%xmm3
movzbl 0x14(%rdi,%rdx,4),%eax
movd   %eax,%xmm0
punpcklbw %xmm3,%xmm0
punpcklwd %xmm1,%xmm0
punpckldq %xmm2,%xmm0
movzbl 0x12(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
movzbl 0x10(%rdi,%rdx,4),%eax
movd   %eax,%xmm2
punpcklbw %xmm1,%xmm2
movzbl 0xe(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
movzbl 0xc(%rdi,%rdx,4),%eax
movd   %eax,%xmm3
punpcklbw %xmm1,%xmm3
punpcklwd %xmm2,%xmm3
movzbl 0xa(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
movzbl 0x8(%rdi,%rdx,4),%eax
movd   %eax,%xmm2
punpcklbw %xmm1,%xmm2
movzbl 0x6(%rdi,%rdx,4),%eax
movd   %eax,%xmm1
movzbl 0x4(%rdi,%rdx,4),%eax
movd   %eax,%xmm4
punpcklbw %xmm1,%xmm4
punpcklwd %xmm2,%xmm4
punpckldq %xmm3,%xmm4
punpcklqdq %xmm0,%xmm4
movdqu %xmm4,0x2(%rsi,%rdx,2)
add    $0x8,%rdx
cmp    %rdx,%r9
jne    1170 <convert_yuv_to_gray0+0x70>
lea    (%r8,%rsi,1),%rdx
add    $0x1,%rdx
nopw   0x0(%rax,%rax,1)
movzbl (%rdi,%rbx,1),%eax
movzbl 0x2(%rdi,%rbx,1),%ecx
mov    %al,-0x1(%rdx)
mov    %cl,(%rdx)
add    $0x4,%rbx
add    $0x2,%rdx
cmp    %r11,%rbx
jb     1260 <convert_yuv_to_gray0+0x160>
xor    %eax,%eax
pop    %rbx
ret

LLVM IR (-O0):
define i32 @convert_yuv_to_gray0(i8* %0, i8* %1, i32 %2, i32 %3) {
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
store i8* %0, i8** %5
store i8* %1, i8** %6
store i32 %2, i32* %7
store i32 %3, i32* %8
store i32 0, i32* %10
store i32 0, i32* %9
br label %13
13: ; preds = %49, %4
%14 = load i32, i32* %9
%15 = load i32, i32* %7
%16 = load i32, i32* %8
%17 = mul i32 %15, %16
%18 = mul i32 %17, 2
%19 = icmp ult i32 %14, %18
br i1 %19, label %20, label %52
20: ; preds = %13
%21 = load i8*, i8** %5
%22 = load i32, i32* %9
%23 = add i32 %22, 0
%24 = zext i32 %23 to i64
%25 = getelementptr inbounds i8, i8* %21, i64 %24
%26 = load i8, i8* %25
%27 = zext i8 %26 to i32
store i32 %27, i32* %11
%28 = load i8*, i8** %5
%29 = load i32, i32* %9
%30 = add i32 %29, 2
%31 = zext i32 %30 to i64
%32 = getelementptr inbounds i8, i8* %28, i64 %31
%33 = load i8, i8* %32
%34 = zext i8 %33 to i32
store i32 %34, i32* %12
%35 = load i32, i32* %11
%36 = trunc i32 %35 to i8
%37 = load i8*, i8** %6
%38 = load i32, i32* %10
%39 = add i32 %38, 1
store i32 %39, i32* %10
%40 = zext i32 %38 to i64
%41 = getelementptr inbounds i8, i8* %37, i64 %40
store i8 %36, i8* %41
%42 = load i32, i32* %12
%43 = trunc i32 %42 to i8
%44 = load i8*, i8** %6
%45 = load i32, i32* %10
%46 = add i32 %45, 1
store i32 %46, i32* %10
%47 = zext i32 %45 to i64
%48 = getelementptr inbounds i8, i8* %44, i64 %47
store i8 %43, i8* %48
br label %49
49: ; preds = %20
%50 = load i32, i32* %9
%51 = add i32 %50, 4
store i32 %51, i32* %9
br label %13
52: ; preds = %13
ret i32 0
}

LLVM IR (-O2):
define i32 @convert_yuv_to_gray0(i8* nocapture %0, i8* nocapture writeonly %1, i32 %2, i32 %3) {
%5 = shl i32 %2, 1
%6 = mul i32 %5, %3
%7 = icmp eq i32 %6, 0
br i1 %7, label %123, label %8
8: ; preds = %4
%9 = zext i32 %6 to i64
%10 = add nsw i64 %9, -1
%11 = lshr i64 %10, 2
%12 = add nuw nsw i64 %11, 1
%13 = icmp ult i64 %10, 32
br i1 %13, label %106, label %14
14: ; preds = %8
%15 = add nsw i64 %9, -1
%16 = lshr i64 %15, 1
%17 = and i64 %16, 9223372036854775806
%18 = add nuw i64 %17, 2
%19 = getelementptr i8, i8* %1, i64 %18
%20 = or i64 %15, 3
%21 = getelementptr i8, i8* %0, i64 %20
%22 = icmp ugt i8* %21, %1
%23 = icmp ugt i8* %19, %0
%24 = and i1 %22, %23
br i1 %24, label %106, label %25
25: ; preds = %14
%26 = and i64 %12, 7
%27 = icmp eq i64 %26, 0
%28 = select i1 %27, i64 8, i64 %26
%29 = sub nsw i64 %12, %28
%30 = shl i64 %29, 1
%31 = shl i64 %29, 2
%32 = getelementptr inbounds i8, i8* %1, i64 -1
br label %33
33: ; preds = %33, %25
%34 = phi i64 [ 0, %25 ], [ %104, %33 ]
%35 = shl i64 %34, 1
%36 = shl i64 %34, 2
%37 = or i64 %36, 4
%38 = or i64 %36, 8
%39 = or i64 %36, 12
%40 = or i64 %36, 16
%41 = or i64 %36, 20
%42 = or i64 %36, 24
%43 = or i64 %36, 28
%44 = getelementptr inbounds i8, i8* %0, i64 %36
%45 = getelementptr inbounds i8, i8* %0, i64 %37
%46 = getelementptr inbounds i8, i8* %0, i64 %38
%47 = getelementptr inbounds i8, i8* %0, i64 %39
%48 = getelementptr inbounds i8, i8* %0, i64 %40
%49 = getelementptr inbounds i8, i8* %0, i64 %41
%50 = getelementptr inbounds i8, i8* %0, i64 %42
%51 = getelementptr inbounds i8, i8* %0, i64 %43
%52 = load i8, i8* %44
%53 = load i8, i8* %45
%54 = load i8, i8* %46
%55 = load i8, i8* %47
%56 = load i8, i8* %48
%57 = load i8, i8* %49
%58 = load i8, i8* %50
%59 = load i8, i8* %51
%60 = insertelement <8 x i8> poison, i8 %52, i64 0
%61 = insertelement <8 x i8> %60, i8 %53, i64 1
%62 = insertelement <8 x i8> %61, i8 %54, i64 2
%63 = insertelement <8 x i8> %62, i8 %55, i64 3
%64 = insertelement <8 x i8> %63, i8 %56, i64 4
%65 = insertelement <8 x i8> %64, i8 %57, i64 5
%66 = insertelement <8 x i8> %65, i8 %58, i64 6
%67 = insertelement <8 x i8> %66, i8 %59, i64 7
%68 = or i64 %36, 2
%69 = or i64 %36, 6
%70 = or i64 %36, 10
%71 = or i64 %36, 14
%72 = or i64 %36, 18
%73 = or i64 %36, 22
%74 = or i64 %36, 26
%75 = or i64 %36, 30
%76 = getelementptr inbounds i8, i8* %0, i64 %68
%77 = getelementptr inbounds i8, i8* %0, i64 %69
%78 = getelementptr inbounds i8, i8* %0, i64 %70
%79 = getelementptr inbounds i8, i8* %0, i64 %71
%80 = getelementptr inbounds i8, i8* %0, i64 %72
%81 = getelementptr inbounds i8, i8* %0, i64 %73
%82 = getelementptr inbounds i8, i8* %0, i64 %74
%83 = getelementptr inbounds i8, i8* %0, i64 %75
%84 = load i8, i8* %76
%85 = load i8, i8* %77
%86 = load i8, i8* %78
%87 = load i8, i8* %79
%88 = load i8, i8* %80
%89 = load i8, i8* %81
%90 = load i8, i8* %82
%91 = load i8, i8* %83
%92 = insertelement <8 x i8> poison, i8 %84, i64 0
%93 = insertelement <8 x i8> %92, i8 %85, i64 1
%94 = insertelement <8 x i8> %93, i8 %86, i64 2
%95 = insertelement <8 x i8> %94, i8 %87, i64 3
%96 = insertelement <8 x i8> %95, i8 %88, i64 4
%97 = insertelement <8 x i8> %96, i8 %89, i64 5
%98 = insertelement <8 x i8> %97, i8 %90, i64 6
%99 = insertelement <8 x i8> %98, i8 %91, i64 7
%100 = or i64 %35, 1
%101 = getelementptr inbounds i8, i8* %32, i64 %100
%102 = bitcast i8* %101 to <16 x i8>*
%103 = shufflevector <8 x i8> %67, <8 x i8> %99, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %103, <16 x i8>* %102
%104 = add nuw i64 %34, 8
%105 = icmp eq i64 %104, %29
br i1 %105, label %106, label %33
106: ; preds = %33, %14, %8
%107 = phi i64 [ 0, %14 ], [ 0, %8 ], [ %30, %33 ]
%108 = phi i64 [ 0, %14 ], [ 0, %8 ], [ %31, %33 ]
br label %109
109: ; preds = %106, %109
%110 = phi i64 [ %119, %109 ], [ %107, %106 ]
%111 = phi i64 [ %121, %109 ], [ %108, %106 ]
%112 = getelementptr inbounds i8, i8* %0, i64 %111
%113 = load i8, i8* %112
%114 = or i64 %111, 2
%115 = getelementptr inbounds i8, i8* %0, i64 %114
%116 = load i8, i8* %115
%117 = or i64 %110, 1
%118 = getelementptr inbounds i8, i8* %1, i64 %110
store i8 %113, i8* %118
%119 = add nuw nsw i64 %110, 2
%120 = getelementptr inbounds i8, i8* %1, i64 %117
store i8 %116, i8* %120
%121 = add nuw nsw i64 %111, 4
%122 = icmp ult i64 %121, %9
br i1 %122, label %109, label %123
123: ; preds = %109, %4
ret i32 0
}