void s_memcpy4rgb(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 int *d = (unsigned 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_memcpy4rgb>:
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_memcpy4rgb+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
mov    %eax,-0x3c(%rbp)
movzbl -0x23(%rbp),%eax
mov    -0x20(%rbp),%ecx
sar    %cl,%eax
mov    0x20(%rbp),%ecx
shl    %cl,%eax
mov    -0x3c(%rbp),%ecx
or     %eax,%ecx
mov    -0x30(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x30(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x30(%rbp)
mov    -0x38(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x38(%rbp)
jmp    1154 <s_memcpy4rgb+0x54>
pop    %rbp
ret

x86 assembly (clang, -O2):
<s_memcpy4rgb>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
test   %edx,%edx
je     11b3 <s_memcpy4rgb+0xb3>
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),%ebx
cmp    $0x7,%ebx
jb     115e <s_memcpy4rgb+0x5e>
lea    (%rsi,%rbx,4),%rax
add    $0x4,%rax
cmp    %rdi,%rax
jbe    11be <s_memcpy4rgb+0xbe>
lea    (%rdi,%rbx,4),%rax
add    $0x4,%rax
cmp    %rsi,%rax
jbe    11be <s_memcpy4rgb+0xbe>
mov    %rsi,%rbp
mov    %rdi,%r8
mov    %edx,%edx
xor    %esi,%esi
nopl   0x0(%rax,%rax,1)
mov    0x0(%rbp,%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    %eax,(%r8,%rsi,4)
add    $0x1,%rsi
cmp    %esi,%edx
jne    1170 <s_memcpy4rgb+0x70>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
add    $0x1,%rbx
mov    %rbx,%r9
and    $0xfffffffffffffff8,%r9
lea    (%rsi,%r9,4),%rbp
lea    (%rdi,%r9,4),%r8
sub    %r9d,%edx
movd   %r12d,%xmm0
movd   %r10d,%xmm1
movd   %r13d,%xmm2
movd   %r15d,%xmm3
movd   %r11d,%xmm7
movd   %r14d,%xmm12
xor    %ecx,%ecx
xorps  %xmm8,%xmm8
xorps  %xmm9,%xmm9
movss  %xmm0,%xmm9
xorps  %xmm11,%xmm11
movss  %xmm1,%xmm11
movdqa 0xded(%rip),%xmm10
xorps  %xmm13,%xmm13
movss  %xmm2,%xmm13
xorps  %xmm5,%xmm5
movss  %xmm3,%xmm5
xorps  %xmm6,%xmm6
movss  %xmm7,%xmm6
movss  %xmm12,%xmm8
nop
movdqu (%rsi,%rcx,4),%xmm7
movdqu 0x10(%rsi,%rcx,4),%xmm0
movdqa %xmm7,%xmm4
psrld  $0x18,%xmm4
movdqa %xmm0,%xmm2
psrld  $0x18,%xmm2
movdqa %xmm7,%xmm3
psrld  $0x10,%xmm3
movdqa %xmm0,%xmm1
psrld  $0x10,%xmm1
psrld  $0x8,%xmm7
psrld  $0x8,%xmm0
psrld  %xmm9,%xmm4
psrld  %xmm9,%xmm2
pslld  %xmm11,%xmm4
pslld  %xmm11,%xmm2
pand   %xmm10,%xmm3
pand   %xmm10,%xmm1
psrld  %xmm13,%xmm3
psrld  %xmm13,%xmm1
pslld  %xmm5,%xmm3
por    %xmm4,%xmm3
pslld  %xmm5,%xmm1
por    %xmm2,%xmm1
pand   %xmm10,%xmm7
pand   %xmm10,%xmm0
psrld  %xmm6,%xmm7
psrld  %xmm6,%xmm0
pslld  %xmm8,%xmm7
por    %xmm3,%xmm7
pslld  %xmm8,%xmm0
por    %xmm1,%xmm0
movdqu %xmm7,(%rdi,%rcx,4)
movdqu %xmm0,0x10(%rdi,%rcx,4)
add    $0x8,%rcx
cmp    %rcx,%r9
jne    1230 <s_memcpy4rgb+0x130>
cmp    %r9,%rbx
jne    1164 <s_memcpy4rgb+0x64>
jmp    11b3 <s_memcpy4rgb+0xb3>

LLVM IR (-O0):
define void @s_memcpy4rgb(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 i32*
%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 i32*
store i32* %25, i32** %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 %75
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 = load i32*, i32** %22
store i32 %69, i32* %70
%71 = load i32*, i32** %22
%72 = getelementptr inbounds i32, i32* %71, i32 1
store i32* %72, i32** %22
%73 = load i32*, i32** %23
%74 = getelementptr inbounds i32, i32* %73, i32 1
store i32* %74, i32** %23
br label %33
75: ; preds = %33
ret void
}

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