void s_memcpy2rgb(void *dest, unsigned int *rgb, int n, int rl, int gl, int bl,
                  int ro, int go, int bo) {
  unsigned char dr;
  unsigned char dg;
  unsigned char db;
  unsigned short int *d = (unsigned short int *)dest;
  unsigned int *s = (unsigned int *)rgb;
  rl = 8 - rl;
  gl = 8 - gl;
  bl = 8 - bl;
  while (n--) {
    dr = *s >> 0x18;
    dg = *s >> 0x10;
    db = *s >> 0x08;
    *d = ((dr >> rl) << ro) | ((dg >> gl) << go) | ((db >> bl) << bo);
    d++;
    s++;
  };
}


x86 assembly (clang, -O0):
<s_memcpy2rgb>:
push   %rbp
mov    %rsp,%rbp
mov    0x20(%rbp),%eax
mov    0x18(%rbp),%eax
mov    0x10(%rbp),%eax
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    %r8d,-0x1c(%rbp)
mov    %r9d,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    $0x8,%eax
sub    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    $0x8,%eax
sub    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    $0x8,%eax
sub    -0x20(%rbp),%eax
mov    %eax,-0x20(%rbp)
mov    -0x14(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x14(%rbp)
cmp    $0x0,%eax
je     11e5 <s_memcpy2rgb+0xe5>
mov    -0x38(%rbp),%rax
mov    (%rax),%eax
shr    $0x18,%eax
mov    %al,-0x21(%rbp)
mov    -0x38(%rbp),%rax
mov    (%rax),%eax
shr    $0x10,%eax
mov    %al,-0x22(%rbp)
mov    -0x38(%rbp),%rax
mov    (%rax),%eax
shr    $0x8,%eax
mov    %al,-0x23(%rbp)
movzbl -0x21(%rbp),%eax
mov    -0x18(%rbp),%ecx
sar    %cl,%eax
mov    0x10(%rbp),%ecx
shl    %cl,%eax
movzbl -0x22(%rbp),%edx
mov    -0x1c(%rbp),%ecx
sar    %cl,%edx
mov    0x18(%rbp),%ecx
shl    %cl,%edx
mov    %edx,%ecx
or     %ecx,%eax
movzbl -0x23(%rbp),%edx
mov    -0x20(%rbp),%ecx
sar    %cl,%edx
mov    0x20(%rbp),%ecx
shl    %cl,%edx
mov    %edx,%ecx
or     %ecx,%eax
mov    %ax,%cx
mov    -0x30(%rbp),%rax
mov    %cx,(%rax)
mov    -0x30(%rbp),%rax
add    $0x2,%rax
mov    %rax,-0x30(%rbp)
mov    -0x38(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x38(%rbp)
jmp    1154 <s_memcpy2rgb+0x54>
pop    %rbp
ret

x86 assembly (clang, -O2):
<s_memcpy2rgb>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
test   %edx,%edx
je     1274 <s_memcpy2rgb+0x174>
mov    0x48(%rsp),%r14d
mov    0x40(%rsp),%r15d
mov    0x38(%rsp),%r10d
mov    $0x8,%r11d
mov    $0x8,%r12d
sub    %ecx,%r12d
mov    $0x8,%r13d
sub    %r8d,%r13d
sub    %r9d,%r11d
lea    -0x1(%rdx),%r8d
cmp    $0x3,%r8d
jae    1151 <s_memcpy2rgb+0x51>
mov    %rsi,%r9
mov    %rdi,%rbp
jmp    1229 <s_memcpy2rgb+0x129>
add    $0x1,%r8
mov    %r8,%rcx
and    $0xfffffffffffffffc,%rcx
lea    (%rsi,%rcx,4),%r9
lea    (%rdi,%rcx,2),%rbp
sub    %ecx,%edx
movd   %r12d,%xmm2
movd   %r10d,%xmm3
movd   %r13d,%xmm5
movd   %r15d,%xmm6
movd   %r11d,%xmm7
movd   %r14d,%xmm8
xor    %ebx,%ebx
xorps  %xmm10,%xmm10
xorps  %xmm1,%xmm1
movss  %xmm2,%xmm1
xorps  %xmm2,%xmm2
movss  %xmm3,%xmm2
movdqa 0xe5f(%rip),%xmm9
xorps  %xmm4,%xmm4
movss  %xmm5,%xmm4
xorps  %xmm5,%xmm5
movss  %xmm6,%xmm5
xorps  %xmm6,%xmm6
movss  %xmm7,%xmm6
movss  %xmm8,%xmm10
nopl   0x0(%rax,%rax,1)
movdqu (%rsi,%rbx,4),%xmm3
movdqa %xmm3,%xmm0
psrld  $0x18,%xmm0
psrld  %xmm1,%xmm0
pslld  %xmm2,%xmm0
movdqa %xmm3,%xmm7
psrld  $0x10,%xmm7
pand   %xmm9,%xmm7
psrld  %xmm4,%xmm7
psrld  $0x8,%xmm3
pslld  %xmm5,%xmm7
pand   %xmm9,%xmm3
psrld  %xmm6,%xmm3
pslld  %xmm10,%xmm3
por    %xmm0,%xmm7
por    %xmm7,%xmm3
pshuflw $0xe8,%xmm3,%xmm0
pshufhw $0xe8,%xmm0,%xmm0
pshufd $0xe8,%xmm0,%xmm0
movq   %xmm0,(%rdi,%rbx,2)
add    $0x4,%rbx
cmp    %rbx,%rcx
jne    11c0 <s_memcpy2rgb+0xc0>
cmp    %rcx,%r8
je     1274 <s_memcpy2rgb+0x174>
mov    %edx,%edx
xor    %esi,%esi
nopl   (%rax)
mov    (%r9,%rsi,4),%eax
mov    %eax,%edi
mov    %eax,%ebx
shr    $0x18,%ebx
mov    %r12d,%ecx
shr    %cl,%ebx
shr    $0x10,%edi
mov    %r10d,%ecx
shl    %cl,%ebx
movzbl %dil,%edi
mov    %r13d,%ecx
shr    %cl,%edi
mov    %r15d,%ecx
shl    %cl,%edi
movzbl %ah,%eax
mov    %r11d,%ecx
shr    %cl,%eax
mov    %r14d,%ecx
shl    %cl,%eax
or     %ebx,%eax
or     %edi,%eax
mov    %ax,0x0(%rbp,%rsi,2)
add    $0x1,%rsi
cmp    %esi,%edx
jne    1230 <s_memcpy2rgb+0x130>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

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