void pixel_pack_portable_s16u8_uv(short int *src, unsigned char *dst,
                                  unsigned int nbpixels) {
  unsigned int i;
  unsigned short *usrc = (unsigned short *)src;
  for (i = 0; i < nbpixels; i++)
    dst[i] = ((usrc[i] ^ 0x8000) >> 8);
}


x86 assembly (clang, -O0):
<pixel_pack_portable_s16u8_uv>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jae    1157 <pixel_pack_portable_s16u8_uv+0x57>
mov    -0x20(%rbp),%rax
mov    -0x18(%rbp),%ecx
movzwl (%rax,%rcx,2),%eax
xor    $0x8000,%eax
sar    $0x8,%eax
mov    %al,%dl
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    111e <pixel_pack_portable_s16u8_uv+0x1e>
pop    %rbp
ret

x86 assembly (clang, -O2):
<pixel_pack_portable_s16u8_uv>:
test   %edx,%edx
je     127d <pixel_pack_portable_s16u8_uv+0x17d>
mov    %edx,%r9d
cmp    $0x10,%edx
jb     1126 <pixel_pack_portable_s16u8_uv+0x26>
lea    (%rdi,%r9,2),%rax
cmp    %rsi,%rax
jbe    1199 <pixel_pack_portable_s16u8_uv+0x99>
lea    (%rsi,%r9,1),%rax
cmp    %rdi,%rax
jbe    1199 <pixel_pack_portable_s16u8_uv+0x99>
xor    %ecx,%ecx
mov    %rcx,%r8
not    %r8
add    %r9,%r8
mov    %r9,%rdx
and    $0x3,%rdx
je     1154 <pixel_pack_portable_s16u8_uv+0x54>
nopw   0x0(%rax,%rax,1)
movzbl 0x1(%rdi,%rcx,2),%eax
xor    $0x80,%al
mov    %al,(%rsi,%rcx,1)
add    $0x1,%rcx
add    $0xffffffffffffffff,%rdx
jne    1140 <pixel_pack_portable_s16u8_uv+0x40>
cmp    $0x3,%r8
jb     127d <pixel_pack_portable_s16u8_uv+0x17d>
xchg   %ax,%ax
movzbl 0x1(%rdi,%rcx,2),%eax
xor    $0x80,%al
mov    %al,(%rsi,%rcx,1)
movzbl 0x3(%rdi,%rcx,2),%eax
xor    $0x80,%al
mov    %al,0x1(%rsi,%rcx,1)
movzbl 0x5(%rdi,%rcx,2),%eax
xor    $0x80,%al
mov    %al,0x2(%rsi,%rcx,1)
movzbl 0x7(%rdi,%rcx,2),%eax
xor    $0x80,%al
mov    %al,0x3(%rsi,%rcx,1)
add    $0x4,%rcx
cmp    %rcx,%r9
jne    1160 <pixel_pack_portable_s16u8_uv+0x60>
jmp    127d <pixel_pack_portable_s16u8_uv+0x17d>
mov    %r9d,%ecx
and    $0xfffffff0,%ecx
lea    -0x10(%rcx),%rax
mov    %rax,%r8
shr    $0x4,%r8
add    $0x1,%r8
test   %rax,%rax
je     127e <pixel_pack_portable_s16u8_uv+0x17e>
mov    %r8,%rax
and    $0xfffffffffffffffe,%rax
xor    %edx,%edx
movdqa 0xe38(%rip),%xmm0
nopl   0x0(%rax,%rax,1)
movdqu (%rdi,%rdx,2),%xmm1
movdqu 0x10(%rdi,%rdx,2),%xmm2
psrlw  $0x8,%xmm1
packuswb %xmm1,%xmm1
psrlw  $0x8,%xmm2
packuswb %xmm2,%xmm2
pxor   %xmm0,%xmm1
pxor   %xmm0,%xmm2
punpcklqdq %xmm2,%xmm1
movdqu %xmm1,(%rsi,%rdx,1)
movdqu 0x20(%rdi,%rdx,2),%xmm1
movdqu 0x30(%rdi,%rdx,2),%xmm2
psrlw  $0x8,%xmm1
packuswb %xmm1,%xmm1
psrlw  $0x8,%xmm2
packuswb %xmm2,%xmm2
pxor   %xmm0,%xmm1
pxor   %xmm0,%xmm2
punpcklqdq %xmm2,%xmm1
movdqu %xmm1,0x10(%rsi,%rdx,1)
add    $0x20,%rdx
add    $0xfffffffffffffffe,%rax
jne    11d0 <pixel_pack_portable_s16u8_uv+0xd0>
test   $0x1,%r8b
je     1274 <pixel_pack_portable_s16u8_uv+0x174>
movdqu (%rdi,%rdx,2),%xmm0
movdqu 0x10(%rdi,%rdx,2),%xmm1
psrlw  $0x8,%xmm0
psrlw  $0x8,%xmm1
packuswb %xmm0,%xmm0
packuswb %xmm1,%xmm1
movdqa 0xd9d(%rip),%xmm2
pxor   %xmm2,%xmm0
pxor   %xmm2,%xmm1
punpcklqdq %xmm1,%xmm0
movdqu %xmm0,(%rsi,%rdx,1)
cmp    %r9,%rcx
jne    1128 <pixel_pack_portable_s16u8_uv+0x28>
ret
xor    %edx,%edx
test   $0x1,%r8b
jne    123e <pixel_pack_portable_s16u8_uv+0x13e>
jmp    1274 <pixel_pack_portable_s16u8_uv+0x174>

LLVM IR (-O0):
define void @pixel_pack_portable_s16u8_uv(i16* %0, i8* %1, i32 %2) {
%4 = alloca i16*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i16*
store i16* %0, i16** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%9 = load i16*, i16** %4
store i16* %9, i16** %8
store i32 0, i32* %7
br label %10
10: ; preds = %28, %3
%11 = load i32, i32* %7
%12 = load i32, i32* %6
%13 = icmp ult i32 %11, %12
br i1 %13, label %14, label %31
14: ; preds = %10
%15 = load i16*, i16** %8
%16 = load i32, i32* %7
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds i16, i16* %15, i64 %17
%19 = load i16, i16* %18
%20 = zext i16 %19 to i32
%21 = xor i32 %20, 32768
%22 = ashr i32 %21, 8
%23 = trunc i32 %22 to i8
%24 = load i8*, i8** %5
%25 = load i32, i32* %7
%26 = zext i32 %25 to i64
%27 = getelementptr inbounds i8, i8* %24, i64 %26
store i8 %23, i8* %27
br label %28
28: ; preds = %14
%29 = load i32, i32* %7
%30 = add i32 %29, 1
store i32 %30, i32* %7
br label %10
31: ; preds = %10
ret void
}

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