void u16pcpy(unsigned short *pdest, const unsigned char *psrc,
             unsigned short *pp, unsigned len) {
  unsigned l;
  if (len) {
    l = len;
    if (l < 961)
      do {
        l--;
        pdest[l] = pp[psrc[l]];
      } while (l);
  };
}


x86 assembly (clang, -O0):
<u16pcpy>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
je     1170 <u16pcpy+0x70>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x20(%rbp)
cmpl   $0x3c1,-0x20(%rbp)
jae    116b <u16pcpy+0x6b>
jmp    1135 <u16pcpy+0x35>
mov    -0x20(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x10(%rbp),%rcx
mov    -0x20(%rbp),%edx
movzbl (%rcx,%rdx,1),%ecx
mov    (%rax,%rcx,2),%dx
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    %dx,(%rax,%rcx,2)
cmpl   $0x0,-0x20(%rbp)
jne    1135 <u16pcpy+0x35>
jmp    116b <u16pcpy+0x6b>
jmp    1170 <u16pcpy+0x70>
pop    %rbp
ret

x86 assembly (clang, -O2):
<u16pcpy>:
lea    -0x1(%rcx),%r8d
cmp    $0x3bf,%r8d
ja     118f <u16pcpy+0x8f>
mov    %ecx,%r9d
and    $0x3,%r9d
je     1135 <u16pcpy+0x35>
nopw   0x0(%rax,%rax,1)
add    $0xffffffff,%ecx
movzbl (%rsi,%rcx,1),%eax
movzwl (%rdx,%rax,2),%eax
mov    %ax,(%rdi,%rcx,2)
add    $0xffffffff,%r9d
jne    1120 <u16pcpy+0x20>
cmp    $0x3,%r8d
jb     118f <u16pcpy+0x8f>
add    $0xfffffffe,%ecx
xchg   %ax,%ax
lea    0x1(%rcx),%r8d
movzbl (%rsi,%r8,1),%eax
movzwl (%rdx,%rax,2),%eax
mov    %ax,(%rdi,%r8,2)
mov    %ecx,%r8d
movzbl (%rsi,%r8,1),%eax
movzwl (%rdx,%rax,2),%eax
mov    %ax,(%rdi,%r8,2)
lea    -0x1(%rcx),%r8d
movzbl (%rsi,%r8,1),%eax
movzwl (%rdx,%rax,2),%eax
mov    %ax,(%rdi,%r8,2)
lea    -0x2(%rcx),%r8d
movzbl (%rsi,%r8,1),%eax
movzwl (%rdx,%rax,2),%eax
mov    %ax,(%rdi,%r8,2)
add    $0xfffffffc,%ecx
cmp    $0xfffffffe,%ecx
jne    1140 <u16pcpy+0x40>
ret

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

LLVM IR (-O2):
define void @u16pcpy(i16* nocapture writeonly %0, i8* nocapture %1, i16* nocapture %2, i32 %3) {
%5 = add i32 %3, -1
%6 = icmp ult i32 %5, 960
br i1 %6, label %7, label %61
7: ; preds = %4
%8 = and i32 %3, 3
%9 = icmp eq i32 %8, 0
br i1 %9, label %23, label %10
10: ; preds = %7, %10
%11 = phi i32 [ %13, %10 ], [ %3, %7 ]
%12 = phi i32 [ %21, %10 ], [ 0, %7 ]
%13 = add i32 %11, -1
%14 = zext i32 %13 to i64
%15 = getelementptr inbounds i8, i8* %1, i64 %14
%16 = load i8, i8* %15
%17 = zext i8 %16 to i64
%18 = getelementptr inbounds i16, i16* %2, i64 %17
%19 = load i16, i16* %18
%20 = getelementptr inbounds i16, i16* %0, i64 %14
store i16 %19, i16* %20
%21 = add i32 %12, 1
%22 = icmp eq i32 %21, %8
br i1 %22, label %23, label %10
23: ; preds = %10, %7
%24 = phi i32 [ %3, %7 ], [ %13, %10 ]
%25 = icmp ult i32 %5, 3
br i1 %25, label %61, label %26
26: ; preds = %23, %26
%27 = phi i32 [ %52, %26 ], [ %24, %23 ]
%28 = add i32 %27, -1
%29 = zext i32 %28 to i64
%30 = getelementptr inbounds i8, i8* %1, i64 %29
%31 = load i8, i8* %30
%32 = zext i8 %31 to i64
%33 = getelementptr inbounds i16, i16* %2, i64 %32
%34 = load i16, i16* %33
%35 = getelementptr inbounds i16, i16* %0, i64 %29
store i16 %34, i16* %35
%36 = add i32 %27, -2
%37 = zext i32 %36 to i64
%38 = getelementptr inbounds i8, i8* %1, i64 %37
%39 = load i8, i8* %38
%40 = zext i8 %39 to i64
%41 = getelementptr inbounds i16, i16* %2, i64 %40
%42 = load i16, i16* %41
%43 = getelementptr inbounds i16, i16* %0, i64 %37
store i16 %42, i16* %43
%44 = add i32 %27, -3
%45 = zext i32 %44 to i64
%46 = getelementptr inbounds i8, i8* %1, i64 %45
%47 = load i8, i8* %46
%48 = zext i8 %47 to i64
%49 = getelementptr inbounds i16, i16* %2, i64 %48
%50 = load i16, i16* %49
%51 = getelementptr inbounds i16, i16* %0, i64 %45
store i16 %50, i16* %51
%52 = add i32 %27, -4
%53 = zext i32 %52 to i64
%54 = getelementptr inbounds i8, i8* %1, i64 %53
%55 = load i8, i8* %54
%56 = zext i8 %55 to i64
%57 = getelementptr inbounds i16, i16* %2, i64 %56
%58 = load i16, i16* %57
%59 = getelementptr inbounds i16, i16* %0, i64 %53
store i16 %58, i16* %59
%60 = icmp eq i32 %52, 0
br i1 %60, label %61, label %26
61: ; preds = %23, %26, %4
ret void
}