void fb_image_convert_32bgrto16(const unsigned char *src, unsigned char *dest,
                                int w) {
  unsigned short *d = (unsigned short *)dest;
  const unsigned int *s = (const unsigned int *)src;
  for (; w; w--) {
    *d++ = (unsigned short)(((*s & 0xFF) >> 3) | ((*s >> 5) & 0x07E0) |
                            ((*s >> 8) & 0xF800));
    s++;
  }
}


x86 assembly (clang, -O0):
<fb_image_convert_32bgrto16>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
cmpl   $0x0,-0x14(%rbp)
je     1188 <fb_image_convert_32bgrto16+0x88>
mov    -0x28(%rbp),%rax
mov    (%rax),%eax
and    $0xff,%eax
shr    $0x3,%eax
mov    -0x28(%rbp),%rcx
mov    (%rcx),%ecx
shr    $0x5,%ecx
and    $0x7e0,%ecx
or     %ecx,%eax
mov    -0x28(%rbp),%rcx
mov    (%rcx),%ecx
shr    $0x8,%ecx
and    $0xf800,%ecx
or     %ecx,%eax
mov    %ax,%cx
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0x2,%rdx
mov    %rdx,-0x20(%rbp)
mov    %cx,(%rax)
mov    -0x28(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x28(%rbp)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
jmp    111f <fb_image_convert_32bgrto16+0x1f>
pop    %rbp
ret

x86 assembly (clang, -O2):
<fb_image_convert_32bgrto16>:
test   %edx,%edx
je     1221 <fb_image_convert_32bgrto16+0x121>
lea    -0x1(%rdx),%r8d
cmp    $0x7,%r8d
jae    111d <fb_image_convert_32bgrto16+0x1d>
mov    %rdi,%r9
mov    %rsi,%r10
jmp    11ec <fb_image_convert_32bgrto16+0xec>
add    $0x1,%r8
mov    %r8,%rax
and    $0xfffffffffffffff8,%rax
lea    (%rdi,%rax,4),%r9
lea    (%rsi,%rax,2),%r10
sub    %eax,%edx
xor    %ecx,%ecx
movdqa 0xec3(%rip),%xmm8
movdqa 0xecb(%rip),%xmm1
movdqa 0xed3(%rip),%xmm2
nopl   (%rax)
movdqu (%rdi,%rcx,4),%xmm4
movdqu 0x10(%rdi,%rcx,4),%xmm6
movdqa %xmm4,%xmm5
psrld  $0x3,%xmm5
movdqa %xmm6,%xmm0
psrld  $0x3,%xmm0
pand   %xmm8,%xmm5
pand   %xmm8,%xmm0
movdqa %xmm4,%xmm7
psrld  $0x5,%xmm7
movdqa %xmm6,%xmm3
psrld  $0x5,%xmm3
pand   %xmm1,%xmm7
por    %xmm5,%xmm7
pand   %xmm1,%xmm3
por    %xmm0,%xmm3
psrld  $0x8,%xmm4
psrld  $0x8,%xmm6
pand   %xmm2,%xmm4
por    %xmm7,%xmm4
pand   %xmm2,%xmm6
por    %xmm3,%xmm6
pshuflw $0xe8,%xmm4,%xmm0
pshufhw $0xe8,%xmm0,%xmm0
pshufd $0xe8,%xmm0,%xmm0
pshuflw $0xe8,%xmm6,%xmm3
pshufhw $0xe8,%xmm3,%xmm3
pshufd $0xe8,%xmm3,%xmm3
punpcklqdq %xmm3,%xmm0
movdqu %xmm0,(%rsi,%rcx,2)
add    $0x8,%rcx
cmp    %rcx,%rax
jne    1150 <fb_image_convert_32bgrto16+0x50>
cmp    %rax,%r8
je     1221 <fb_image_convert_32bgrto16+0x121>
mov    %edx,%eax
xor    %ecx,%ecx
mov    (%r9,%rcx,4),%edx
mov    %edx,%esi
shr    $0x3,%esi
and    $0x1f,%esi
mov    %edx,%edi
shr    $0x5,%edi
and    $0x7e0,%edi
or     %esi,%edi
shr    $0x8,%edx
and    $0xf800,%edx
or     %edi,%edx
mov    %dx,(%r10,%rcx,2)
add    $0x1,%rcx
cmp    %ecx,%eax
jne    11f0 <fb_image_convert_32bgrto16+0xf0>
ret

LLVM IR (-O0):
define void @fb_image_convert_32bgrto16(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i16*
%8 = alloca i32*
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%9 = load i8*, i8** %5
%10 = bitcast i8* %9 to i16*
store i16* %10, i16** %7
%11 = load i8*, i8** %4
%12 = bitcast i8* %11 to i32*
store i32* %12, i32** %8
br label %13
13: ; preds = %36, %3
%14 = load i32, i32* %6
%15 = icmp ne i32 %14, 0
br i1 %15, label %16, label %39
16: ; preds = %13
%17 = load i32*, i32** %8
%18 = load i32, i32* %17
%19 = and i32 %18, 255
%20 = lshr i32 %19, 3
%21 = load i32*, i32** %8
%22 = load i32, i32* %21
%23 = lshr i32 %22, 5
%24 = and i32 %23, 2016
%25 = or i32 %20, %24
%26 = load i32*, i32** %8
%27 = load i32, i32* %26
%28 = lshr i32 %27, 8
%29 = and i32 %28, 63488
%30 = or i32 %25, %29
%31 = trunc i32 %30 to i16
%32 = load i16*, i16** %7
%33 = getelementptr inbounds i16, i16* %32, i32 1
store i16* %33, i16** %7
store i16 %31, i16* %32
%34 = load i32*, i32** %8
%35 = getelementptr inbounds i32, i32* %34, i32 1
store i32* %35, i32** %8
br label %36
36: ; preds = %16
%37 = load i32, i32* %6
%38 = add nsw i32 %37, -1
store i32 %38, i32* %6
br label %13
39: ; preds = %13
ret void
}

LLVM IR (-O2):
define void @fb_image_convert_32bgrto16(i8* nocapture %0, i8* nocapture writeonly %1, i32 %2) {
%4 = icmp eq i32 %2, 0
br i1 %4, label %74, label %5
5: ; preds = %3
%6 = bitcast i8* %0 to i32*
%7 = bitcast i8* %1 to i16*
%8 = add i32 %2, -1
%9 = zext i32 %8 to i64
%10 = add nuw nsw i64 %9, 1
%11 = icmp ult i32 %8, 7
br i1 %11, label %52, label %12
12: ; preds = %5
%13 = and i64 %10, 8589934584
%14 = getelementptr i32, i32* %6, i64 %13
%15 = getelementptr i16, i16* %7, i64 %13
%16 = trunc i64 %13 to i32
%17 = sub i32 %2, %16
br label %18
18: ; preds = %18, %12
%19 = phi i64 [ 0, %12 ], [ %48, %18 ]
%20 = getelementptr i32, i32* %6, i64 %19
%21 = getelementptr i16, i16* %7, i64 %19
%22 = bitcast i32* %20 to <4 x i32>*
%23 = load <4 x i32>, <4 x i32>* %22
%24 = getelementptr i32, i32* %20, i64 4
%25 = bitcast i32* %24 to <4 x i32>*
%26 = load <4 x i32>, <4 x i32>* %25
%27 = lshr <4 x i32> %23, <i32 3, i32 3, i32 3, i32 3>
%28 = lshr <4 x i32> %26, <i32 3, i32 3, i32 3, i32 3>
%29 = and <4 x i32> %27, <i32 31, i32 31, i32 31, i32 31>
%30 = and <4 x i32> %28, <i32 31, i32 31, i32 31, i32 31>
%31 = lshr <4 x i32> %23, <i32 5, i32 5, i32 5, i32 5>
%32 = lshr <4 x i32> %26, <i32 5, i32 5, i32 5, i32 5>
%33 = and <4 x i32> %31, <i32 2016, i32 2016, i32 2016, i32 2016>
%34 = and <4 x i32> %32, <i32 2016, i32 2016, i32 2016, i32 2016>
%35 = or <4 x i32> %29, %33
%36 = or <4 x i32> %30, %34
%37 = lshr <4 x i32> %23, <i32 8, i32 8, i32 8, i32 8>
%38 = lshr <4 x i32> %26, <i32 8, i32 8, i32 8, i32 8>
%39 = and <4 x i32> %37, <i32 63488, i32 63488, i32 63488, i32 63488>
%40 = and <4 x i32> %38, <i32 63488, i32 63488, i32 63488, i32 63488>
%41 = or <4 x i32> %35, %39
%42 = or <4 x i32> %36, %40
%43 = trunc <4 x i32> %41 to <4 x i16>
%44 = trunc <4 x i32> %42 to <4 x i16>
%45 = bitcast i16* %21 to <4 x i16>*
store <4 x i16> %43, <4 x i16>* %45
%46 = getelementptr i16, i16* %21, i64 4
%47 = bitcast i16* %46 to <4 x i16>*
store <4 x i16> %44, <4 x i16>* %47
%48 = add nuw i64 %19, 8
%49 = icmp eq i64 %48, %13
br i1 %49, label %50, label %18
50: ; preds = %18
%51 = icmp eq i64 %10, %13
br i1 %51, label %74, label %52
52: ; preds = %5, %50
%53 = phi i32* [ %6, %5 ], [ %14, %50 ]
%54 = phi i16* [ %7, %5 ], [ %15, %50 ]
%55 = phi i32 [ %2, %5 ], [ %17, %50 ]
br label %56
56: ; preds = %52, %56
%57 = phi i32* [ %71, %56 ], [ %53, %52 ]
%58 = phi i16* [ %70, %56 ], [ %54, %52 ]
%59 = phi i32 [ %72, %56 ], [ %55, %52 ]
%60 = load i32, i32* %57
%61 = lshr i32 %60, 3
%62 = and i32 %61, 31
%63 = lshr i32 %60, 5
%64 = and i32 %63, 2016
%65 = or i32 %62, %64
%66 = lshr i32 %60, 8
%67 = and i32 %66, 63488
%68 = or i32 %65, %67
%69 = trunc i32 %68 to i16
%70 = getelementptr inbounds i16, i16* %58, i64 1
store i16 %69, i16* %58
%71 = getelementptr inbounds i32, i32* %57, i64 1
%72 = add nsw i32 %59, -1
%73 = icmp eq i32 %72, 0
br i1 %73, label %74, label %56
74: ; preds = %56, %50, %3
ret void
}