void bgr888_to_rgb565(void *dst_, const void *src_, int bytes) {
  const unsigned char *src = src_;
  unsigned int *dst = dst_;
  unsigned int r1, g1, b1, r2, g2, b2;
  for (; bytes >= 6; bytes -= 6, src += 6, dst++) {
    r1 = src[0] & 0xf8;
    g1 = src[1] & 0xfc;
    b1 = src[2] & 0xf8;
    r2 = src[3] & 0xf8;
    g2 = src[4] & 0xfc;
    b2 = src[5] & 0xf8;
    *dst = (r2 << 24) | (g2 << 19) | (b2 << 13) | (r1 << 8) | (g1 << 3) |
           (b1 >> 3);
  }
}


x86 assembly (clang, -O0):
<bgr888_to_rgb565>:
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   $0x6,-0x14(%rbp)
jl     11e2 <bgr888_to_rgb565+0xe2>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
and    $0xf8,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x20(%rbp),%rax
movzbl 0x1(%rax),%eax
and    $0xfc,%eax
mov    %eax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
movzbl 0x2(%rax),%eax
and    $0xf8,%eax
mov    %eax,-0x34(%rbp)
mov    -0x20(%rbp),%rax
movzbl 0x3(%rax),%eax
and    $0xf8,%eax
mov    %eax,-0x38(%rbp)
mov    -0x20(%rbp),%rax
movzbl 0x4(%rax),%eax
and    $0xfc,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x20(%rbp),%rax
movzbl 0x5(%rax),%eax
and    $0xf8,%eax
mov    %eax,-0x40(%rbp)
mov    -0x38(%rbp),%ecx
shl    $0x18,%ecx
mov    -0x3c(%rbp),%eax
shl    $0x13,%eax
or     %eax,%ecx
mov    -0x40(%rbp),%eax
shl    $0xd,%eax
or     %eax,%ecx
mov    -0x2c(%rbp),%eax
shl    $0x8,%eax
or     %eax,%ecx
mov    -0x30(%rbp),%eax
shl    $0x3,%eax
or     %eax,%ecx
mov    -0x34(%rbp),%eax
shr    $0x3,%eax
or     %eax,%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x14(%rbp),%eax
sub    $0x6,%eax
mov    %eax,-0x14(%rbp)
mov    -0x20(%rbp),%rax
add    $0x6,%rax
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x28(%rbp)
jmp    111f <bgr888_to_rgb565+0x1f>
pop    %rbp
ret

x86 assembly (clang, -O2):
<bgr888_to_rgb565>:
push   %r14
push   %rbx
cmp    $0x6,%edx
jl     11cb <bgr888_to_rgb565+0xcb>
xor    %eax,%eax
mov    %edx,%r8d
sub    $0xb,%r8d
cmovb  %eax,%r8d
add    $0x5,%r8d
cmp    $0x12,%r8d
jb     115e <bgr888_to_rgb565+0x5e>
mov    $0xaaaaaaab,%r9d
mov    %edx,%ecx
sub    $0xb,%ecx
cmovb  %eax,%ecx
add    $0x5,%ecx
imul   %r9,%rcx
shr    $0x22,%rcx
lea    (%rcx,%rcx,2),%rax
lea    (%rsi,%rax,2),%rax
add    $0x6,%rax
cmp    %rdi,%rax
jbe    11cf <bgr888_to_rgb565+0xcf>
lea    (%rdi,%rcx,4),%rax
add    $0x4,%rax
cmp    %rsi,%rax
jbe    11cf <bgr888_to_rgb565+0xcf>
mov    %rsi,%r14
mov    %rdi,%r11
add    $0x6,%edx
nopw   0x0(%rax,%rax,1)
movzbl (%r14),%esi
and    $0xfffffff8,%esi
movzbl 0x1(%r14),%r8d
and    $0xfffffffc,%r8d
movzbl 0x2(%r14),%edi
movzbl 0x3(%r14),%eax
and    $0xfffffff8,%eax
movzbl 0x4(%r14),%ebx
and    $0xfffffffc,%ebx
movzbl 0x5(%r14),%ecx
and    $0xfffffff8,%ecx
shl    $0x18,%eax
shl    $0x13,%ebx
or     %eax,%ebx
shl    $0xd,%ecx
or     %ebx,%ecx
shl    $0x8,%esi
or     %ecx,%esi
lea    (%rsi,%r8,8),%eax
shr    $0x3,%edi
or     %eax,%edi
mov    %edi,(%r11)
add    $0x4,%r11
add    $0xfffffffa,%edx
add    $0x6,%r14
cmp    $0xb,%edx
ja     1170 <bgr888_to_rgb565+0x70>
pop    %rbx
pop    %r14
ret
imul   %r9,%r8
shr    $0x22,%r8
add    $0x1,%r8d
mov    %r8d,%r9d
and    $0xfffffffc,%r9d
lea    (%r9,%r9,1),%eax
lea    (%rax,%rax,2),%eax
sub    %eax,%edx
lea    (%r9,%r9,2),%rax
lea    (%rsi,%rax,2),%r14
lea    (%rdi,%r9,4),%r11
xor    %r10d,%r10d
movaps 0xdfe(%rip),%xmm10
movaps 0xe06(%rip),%xmm15
pxor   %xmm2,%xmm2
movdqa 0xe09(%rip),%xmm11
movaps 0xe11(%rip),%xmm13
movdqa 0xe18(%rip),%xmm12
movdqa 0xe1f(%rip),%xmm14
movdqa 0xe26(%rip),%xmm8
movdqa 0xe2d(%rip),%xmm9
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movups (%rsi),%xmm7
movsd  0x10(%rsi),%xmm0
movaps %xmm10,%xmm3
andnps %xmm0,%xmm3
movaps %xmm7,%xmm4
movaps %xmm7,%xmm6
movaps %xmm0,%xmm5
shufps $0x1,%xmm7,%xmm5
shufps $0xe2,%xmm7,%xmm5
movaps %xmm13,%xmm1
andnps %xmm7,%xmm1
andps  %xmm10,%xmm7
orps   %xmm3,%xmm7
punpckhbw %xmm2,%xmm4
movdqa %xmm4,%xmm3
psrld  $0x10,%xmm3
punpcklbw %xmm2,%xmm6
pshufd $0xc4,%xmm6,%xmm6
pshufhw $0xed,%xmm6,%xmm6
punpckhdq %xmm3,%xmm6
packuswb %xmm6,%xmm6
pand   %xmm11,%xmm6
movdqa %xmm11,%xmm3
pandn  %xmm0,%xmm3
por    %xmm6,%xmm3
andps  %xmm13,%xmm0
orps   %xmm1,%xmm0
movaps %xmm0,%xmm1
punpcklbw %xmm2,%xmm0
shufps $0x1,%xmm0,%xmm4
shufps $0xe2,%xmm0,%xmm4
andps  %xmm15,%xmm1
pshufd $0x27,%xmm1,%xmm0
pshufhw $0xe6,%xmm0,%xmm0
pshufd $0xe6,%xmm0,%xmm0
pshuflw $0xc6,%xmm0,%xmm6
packuswb %xmm6,%xmm6
pshuflw $0xe7,%xmm4,%xmm0
pshufhw $0xe7,%xmm0,%xmm0
pshufd $0xe8,%xmm0,%xmm0
pshuflw $0x93,%xmm0,%xmm0
packuswb %xmm0,%xmm0
pand   %xmm14,%xmm6
punpcklbw %xmm2,%xmm6
punpcklwd %xmm2,%xmm6
pand   %xmm12,%xmm0
punpcklbw %xmm2,%xmm0
punpcklwd %xmm2,%xmm0
pslld  $0x13,%xmm6
pslld  $0xd,%xmm0
por    %xmm6,%xmm0
andps  %xmm15,%xmm7
pshufd $0xd8,%xmm7,%xmm1
pshufhw $0xe6,%xmm1,%xmm1
pshufd $0xe8,%xmm1,%xmm1
pshuflw $0x6c,%xmm1,%xmm1
packuswb %xmm1,%xmm1
pshuflw $0xe6,%xmm5,%xmm4
pshufhw $0xec,%xmm4,%xmm4
pand   %xmm12,%xmm1
punpcklbw %xmm2,%xmm1
punpcklwd %xmm2,%xmm1
pslld  $0x8,%xmm1
por    %xmm0,%xmm1
pshufd $0xe8,%xmm4,%xmm0
pshuflw $0xc6,%xmm0,%xmm0
punpcklbw %xmm0,%xmm0
pshuflw $0xd7,%xmm0,%xmm0
pshufhw $0xd7,%xmm0,%xmm0
pand   %xmm8,%xmm0
pslld  $0x18,%xmm0
por    %xmm0,%xmm1
pand   %xmm14,%xmm3
punpcklbw %xmm2,%xmm3
punpcklwd %xmm2,%xmm3
pslld  $0x3,%xmm3
por    %xmm1,%xmm3
pand   %xmm15,%xmm4
pshufd $0xe8,%xmm4,%xmm0
pshuflw $0x39,%xmm0,%xmm0
packuswb %xmm0,%xmm0
psrlw  $0x3,%xmm0
pand   %xmm9,%xmm0
punpcklbw %xmm2,%xmm0
punpcklwd %xmm2,%xmm0
por    %xmm3,%xmm0
movdqu %xmm0,(%rdi,%r10,4)
add    $0x4,%r10
add    $0x18,%rsi
cmp    %r10,%r9
jne    1250 <bgr888_to_rgb565+0x150>
cmp    %r8,%r9
jne    1164 <bgr888_to_rgb565+0x64>
jmp    11cb <bgr888_to_rgb565+0xcb>

LLVM IR (-O0):
define void @bgr888_to_rgb565(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i32*
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%15 = load i8*, i8** %5
store i8* %15, i8** %7
%16 = load i8*, i8** %4
%17 = bitcast i8* %16 to i32*
store i32* %17, i32** %8
br label %18
18: ; preds = %70, %3
%19 = load i32, i32* %6
%20 = icmp sge i32 %19, 6
br i1 %20, label %21, label %77
21: ; preds = %18
%22 = load i8*, i8** %7
%23 = getelementptr inbounds i8, i8* %22, i64 0
%24 = load i8, i8* %23
%25 = zext i8 %24 to i32
%26 = and i32 %25, 248
store i32 %26, i32* %9
%27 = load i8*, i8** %7
%28 = getelementptr inbounds i8, i8* %27, i64 1
%29 = load i8, i8* %28
%30 = zext i8 %29 to i32
%31 = and i32 %30, 252
store i32 %31, i32* %10
%32 = load i8*, i8** %7
%33 = getelementptr inbounds i8, i8* %32, i64 2
%34 = load i8, i8* %33
%35 = zext i8 %34 to i32
%36 = and i32 %35, 248
store i32 %36, i32* %11
%37 = load i8*, i8** %7
%38 = getelementptr inbounds i8, i8* %37, i64 3
%39 = load i8, i8* %38
%40 = zext i8 %39 to i32
%41 = and i32 %40, 248
store i32 %41, i32* %12
%42 = load i8*, i8** %7
%43 = getelementptr inbounds i8, i8* %42, i64 4
%44 = load i8, i8* %43
%45 = zext i8 %44 to i32
%46 = and i32 %45, 252
store i32 %46, i32* %13
%47 = load i8*, i8** %7
%48 = getelementptr inbounds i8, i8* %47, i64 5
%49 = load i8, i8* %48
%50 = zext i8 %49 to i32
%51 = and i32 %50, 248
store i32 %51, i32* %14
%52 = load i32, i32* %12
%53 = shl i32 %52, 24
%54 = load i32, i32* %13
%55 = shl i32 %54, 19
%56 = or i32 %53, %55
%57 = load i32, i32* %14
%58 = shl i32 %57, 13
%59 = or i32 %56, %58
%60 = load i32, i32* %9
%61 = shl i32 %60, 8
%62 = or i32 %59, %61
%63 = load i32, i32* %10
%64 = shl i32 %63, 3
%65 = or i32 %62, %64
%66 = load i32, i32* %11
%67 = lshr i32 %66, 3
%68 = or i32 %65, %67
%69 = load i32*, i32** %8
store i32 %68, i32* %69
br label %70
70: ; preds = %21
%71 = load i32, i32* %6
%72 = sub nsw i32 %71, 6
store i32 %72, i32* %6
%73 = load i8*, i8** %7
%74 = getelementptr inbounds i8, i8* %73, i64 6
store i8* %74, i8** %7
%75 = load i32*, i32** %8
%76 = getelementptr inbounds i32, i32* %75, i32 1
store i32* %76, i32** %8
br label %18
77: ; preds = %18
ret void
}

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