unsigned long nibble_sort_word_payer(unsigned long arg) {
  unsigned long counts = 0;
  counts += 1ul << ((arg & 0xF) << 2);
  counts += 1ul << ((arg & 0xF0) >> 2);
  counts += 1ul << ((arg & 0xF00) >> 6);
  counts += 1ul << ((arg & 0xF000) >> 10);
  counts += 1ul << ((arg & 0xF0000) >> 14);
  counts += 1ul << ((arg & 0xF00000) >> 18);
  counts += 1ul << ((arg & 0xF000000) >> 22);
  counts += 1ul << ((arg & 0xF0000000) >> 26);
  counts += 1ul << ((arg & 0xF00000000) >> 30);
  counts += 1ul << ((arg & 0xF000000000) >> 34);
  counts += 1ul << ((arg & 0xF0000000000) >> 38);
  counts += 1ul << ((arg & 0xF00000000000) >> 42);
  counts += 1ul << ((arg & 0xF000000000000) >> 46);
  counts += 1ul << ((arg & 0xF0000000000000) >> 50);
  counts += 1ul << ((arg & 0xF00000000000000) >> 54);
  counts += 1ul << ((arg & 0xF000000000000000) >> 58);
  if (counts == 0 || (counts & (counts - 1)) == 0)
    return arg;
  unsigned long cur_mask = 0xF000000000000000;
  unsigned long cur_nr = 0xF;
  unsigned long ret = 0;
  while (cur_mask != 0) {
    if ((counts & cur_mask) == 0) {
      cur_mask = cur_mask >> 4;
      cur_nr--;
      continue;
    }
    ret = (ret << 4) | cur_nr;
    counts -= 1ull << (cur_nr << 2);
  }
  return ret;
}


x86 assembly (clang, -O0):
<nibble_sort_word_payer>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
movq   $0x0,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf,%rcx
shl    $0x2,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf0,%rcx
shr    $0x2,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf00,%rcx
shr    $0x6,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf000,%rcx
shr    $0xa,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf0000,%rcx
shr    $0xe,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf00000,%rcx
shr    $0x12,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rcx
and    $0xf000000,%rcx
shr    $0x16,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf0000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x1a,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf00000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x1e,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x22,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf0000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x26,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf00000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x2a,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf000000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x2e,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf0000000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x32,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf00000000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x36,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf000000000000000,%rcx
and    -0x10(%rbp),%rcx
shr    $0x3a,%rcx
mov    $0x1,%eax
shl    %cl,%rax
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
je     133c <nibble_sort_word_payer+0x23c>
mov    -0x18(%rbp),%rax
mov    -0x18(%rbp),%rcx
sub    $0x1,%rcx
and    %rcx,%rax
cmp    $0x0,%rax
jne    1349 <nibble_sort_word_payer+0x249>
mov    -0x10(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    13dc <nibble_sort_word_payer+0x2dc>
movabs $0xf000000000000000,%rax
mov    %rax,-0x20(%rbp)
movq   $0xf,-0x28(%rbp)
movq   $0x0,-0x30(%rbp)
cmpq   $0x0,-0x20(%rbp)
je     13d4 <nibble_sort_word_payer+0x2d4>
mov    -0x18(%rbp),%rax
and    -0x20(%rbp),%rax
cmp    $0x0,%rax
jne    13a1 <nibble_sort_word_payer+0x2a1>
mov    -0x20(%rbp),%rax
shr    $0x4,%rax
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x28(%rbp)
jmp    1367 <nibble_sort_word_payer+0x267>
mov    -0x30(%rbp),%rax
shl    $0x4,%rax
or     -0x28(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x28(%rbp),%rcx
shl    $0x2,%rcx
mov    $0x1,%eax
shl    %cl,%rax
mov    %rax,%rcx
mov    -0x18(%rbp),%rax
sub    %rcx,%rax
mov    %rax,-0x18(%rbp)
jmp    1367 <nibble_sort_word_payer+0x267>
mov    -0x30(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<nibble_sort_word_payer>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %rdi,%rax
lea    0x0(,%rdi,4),%ecx
mov    $0x1,%r8d
shl    %cl,%r8
mov    %eax,%ecx
shr    $0x2,%cl
and    $0x3c,%cl
mov    $0x1,%r9d
shl    %cl,%r9
mov    %rdi,%rcx
shr    $0x6,%rcx
and    $0x3c,%cl
mov    $0x1,%r10d
shl    %cl,%r10
mov    %rdi,%rcx
shr    $0xa,%rcx
and    $0x3c,%cl
mov    $0x1,%r11d
shl    %cl,%r11
mov    %rdi,%rcx
shr    $0xe,%rcx
and    $0x3c,%cl
mov    $0x1,%r14d
shl    %cl,%r14
mov    %rdi,%rcx
shr    $0x12,%rcx
and    $0x3c,%cl
mov    $0x1,%r15d
shl    %cl,%r15
mov    %rdi,%rcx
shr    $0x16,%rcx
and    $0x3c,%cl
mov    $0x1,%r12d
shl    %cl,%r12
mov    %rdi,%rcx
shr    $0x1a,%rcx
and    $0x3c,%cl
mov    $0x1,%r13d
shl    %cl,%r13
add    %r8,%r9
mov    %rdi,%rcx
shr    $0x1e,%rcx
and    $0x3c,%cl
mov    $0x1,%edx
shl    %cl,%rdx
add    %r9,%r10
add    %r10,%r11
mov    %rdi,%rcx
shr    $0x22,%rcx
and    $0x3c,%cl
mov    $0x1,%edi
shl    %cl,%rdi
add    %r11,%r14
add    %r14,%r15
mov    %rax,%rcx
shr    $0x26,%rcx
and    $0x3c,%cl
mov    $0x1,%esi
shl    %cl,%rsi
add    %r15,%r12
add    %r12,%r13
mov    %rax,%rcx
shr    $0x2a,%rcx
and    $0x3c,%cl
mov    $0x1,%ebx
shl    %cl,%rbx
add    %r13,%rdx
add    %rdx,%rdi
mov    %rax,%rcx
shr    $0x2e,%rcx
and    $0x3c,%cl
mov    $0x1,%edx
shl    %cl,%rdx
add    %rdi,%rsi
add    %rsi,%rbx
mov    %rax,%rcx
shr    $0x32,%rcx
and    $0x3c,%cl
mov    $0x1,%esi
shl    %cl,%rsi
add    %rbx,%rdx
add    %rdx,%rsi
mov    %rax,%rcx
shr    $0x36,%rcx
and    $0x3c,%cl
mov    $0x1,%edi
shl    %cl,%rdi
mov    $0x1,%edx
add    %rsi,%rdi
mov    %rax,%rcx
shr    $0x3a,%rcx
and    $0x3c,%cl
shl    %cl,%rdx
add    %rdi,%rdx
je     1316 <nibble_sort_word_payer+0x216>
mov    %rdx,%rcx
shr    %rcx
movabs $0x5555555555555555,%rsi
55 55 55
and    %rcx,%rsi
mov    %rdx,%rcx
sub    %rsi,%rcx
movabs $0x3333333333333333,%rsi
33 33 33
mov    %rcx,%rdi
and    %rsi,%rdi
shr    $0x2,%rcx
and    %rsi,%rcx
add    %rdi,%rcx
mov    %rcx,%rsi
shr    $0x4,%rsi
add    %rcx,%rsi
movabs $0xf0f0f0f0f0f0f0f,%rcx
0f 0f 0f
and    %rsi,%rcx
movabs $0x101010101010101,%rsi
01 01 01
imul   %rcx,%rsi
shr    $0x38,%rsi
cmp    $0x2,%esi
jb     1316 <nibble_sort_word_payer+0x216>
mov    $0xf,%esi
movabs $0xf000000000000000,%rbx
xor    %eax,%eax
lea    0x0(,%rsi,4),%rcx
nopl   0x0(%rax)
test   %rdx,%rbx
jne    1300 <nibble_sort_word_payer+0x200>
mov    %rbx,%rdi
shr    $0x4,%rdi
add    $0xffffffffffffffff,%rsi
add    $0xfffffffffffffffc,%rcx
cmp    $0x10,%rbx
mov    %rdi,%rbx
jae    12e0 <nibble_sort_word_payer+0x1e0>
jmp    1316 <nibble_sort_word_payer+0x216>
nop
shl    $0x4,%rax
or     %rsi,%rax
mov    $0xffffffffffffffff,%rdi
shl    %cl,%rdi
add    %rdi,%rdx
jmp    12d4 <nibble_sort_word_payer+0x1d4>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define i64 @nibble_sort_word_payer(i64 %0) {
%2 = alloca i64
%3 = alloca i64
%4 = alloca i64
%5 = alloca i64
%6 = alloca i64
%7 = alloca i64
store i64 %0, i64* %3
store i64 0, i64* %4
%8 = load i64, i64* %3
%9 = and i64 %8, 15
%10 = shl i64 %9, 2
%11 = shl i64 1, %10
%12 = load i64, i64* %4
%13 = add i64 %12, %11
store i64 %13, i64* %4
%14 = load i64, i64* %3
%15 = and i64 %14, 240
%16 = lshr i64 %15, 2
%17 = shl i64 1, %16
%18 = load i64, i64* %4
%19 = add i64 %18, %17
store i64 %19, i64* %4
%20 = load i64, i64* %3
%21 = and i64 %20, 3840
%22 = lshr i64 %21, 6
%23 = shl i64 1, %22
%24 = load i64, i64* %4
%25 = add i64 %24, %23
store i64 %25, i64* %4
%26 = load i64, i64* %3
%27 = and i64 %26, 61440
%28 = lshr i64 %27, 10
%29 = shl i64 1, %28
%30 = load i64, i64* %4
%31 = add i64 %30, %29
store i64 %31, i64* %4
%32 = load i64, i64* %3
%33 = and i64 %32, 983040
%34 = lshr i64 %33, 14
%35 = shl i64 1, %34
%36 = load i64, i64* %4
%37 = add i64 %36, %35
store i64 %37, i64* %4
%38 = load i64, i64* %3
%39 = and i64 %38, 15728640
%40 = lshr i64 %39, 18
%41 = shl i64 1, %40
%42 = load i64, i64* %4
%43 = add i64 %42, %41
store i64 %43, i64* %4
%44 = load i64, i64* %3
%45 = and i64 %44, 251658240
%46 = lshr i64 %45, 22
%47 = shl i64 1, %46
%48 = load i64, i64* %4
%49 = add i64 %48, %47
store i64 %49, i64* %4
%50 = load i64, i64* %3
%51 = and i64 %50, 4026531840
%52 = lshr i64 %51, 26
%53 = shl i64 1, %52
%54 = load i64, i64* %4
%55 = add i64 %54, %53
store i64 %55, i64* %4
%56 = load i64, i64* %3
%57 = and i64 %56, 64424509440
%58 = lshr i64 %57, 30
%59 = shl i64 1, %58
%60 = load i64, i64* %4
%61 = add i64 %60, %59
store i64 %61, i64* %4
%62 = load i64, i64* %3
%63 = and i64 %62, 1030792151040
%64 = lshr i64 %63, 34
%65 = shl i64 1, %64
%66 = load i64, i64* %4
%67 = add i64 %66, %65
store i64 %67, i64* %4
%68 = load i64, i64* %3
%69 = and i64 %68, 16492674416640
%70 = lshr i64 %69, 38
%71 = shl i64 1, %70
%72 = load i64, i64* %4
%73 = add i64 %72, %71
store i64 %73, i64* %4
%74 = load i64, i64* %3
%75 = and i64 %74, 263882790666240
%76 = lshr i64 %75, 42
%77 = shl i64 1, %76
%78 = load i64, i64* %4
%79 = add i64 %78, %77
store i64 %79, i64* %4
%80 = load i64, i64* %3
%81 = and i64 %80, 4222124650659840
%82 = lshr i64 %81, 46
%83 = shl i64 1, %82
%84 = load i64, i64* %4
%85 = add i64 %84, %83
store i64 %85, i64* %4
%86 = load i64, i64* %3
%87 = and i64 %86, 67553994410557440
%88 = lshr i64 %87, 50
%89 = shl i64 1, %88
%90 = load i64, i64* %4
%91 = add i64 %90, %89
store i64 %91, i64* %4
%92 = load i64, i64* %3
%93 = and i64 %92, 1080863910568919040
%94 = lshr i64 %93, 54
%95 = shl i64 1, %94
%96 = load i64, i64* %4
%97 = add i64 %96, %95
store i64 %97, i64* %4
%98 = load i64, i64* %3
%99 = and i64 %98, -1152921504606846976
%100 = lshr i64 %99, 58
%101 = shl i64 1, %100
%102 = load i64, i64* %4
%103 = add i64 %102, %101
store i64 %103, i64* %4
%104 = load i64, i64* %4
%105 = icmp eq i64 %104, 0
br i1 %105, label %112, label %106
106: ; preds = %1
%107 = load i64, i64* %4
%108 = load i64, i64* %4
%109 = sub i64 %108, 1
%110 = and i64 %107, %109
%111 = icmp eq i64 %110, 0
br i1 %111, label %112, label %114
112: ; preds = %106, %1
%113 = load i64, i64* %3
store i64 %113, i64* %2
br label %140
114: ; preds = %106
store i64 -1152921504606846976, i64* %5
store i64 15, i64* %6
store i64 0, i64* %7
br label %115
115: ; preds = %128, %123, %114
%116 = load i64, i64* %5
%117 = icmp ne i64 %116, 0
br i1 %117, label %118, label %138
118: ; preds = %115
%119 = load i64, i64* %4
%120 = load i64, i64* %5
%121 = and i64 %119, %120
%122 = icmp eq i64 %121, 0
br i1 %122, label %123, label %128
123: ; preds = %118
%124 = load i64, i64* %5
%125 = lshr i64 %124, 4
store i64 %125, i64* %5
%126 = load i64, i64* %6
%127 = add i64 %126, -1
store i64 %127, i64* %6
br label %115
128: ; preds = %118
%129 = load i64, i64* %7
%130 = shl i64 %129, 4
%131 = load i64, i64* %6
%132 = or i64 %130, %131
store i64 %132, i64* %7
%133 = load i64, i64* %6
%134 = shl i64 %133, 2
%135 = shl i64 1, %134
%136 = load i64, i64* %4
%137 = sub i64 %136, %135
store i64 %137, i64* %4
br label %115
138: ; preds = %115
%139 = load i64, i64* %7
store i64 %139, i64* %2
br label %140
140: ; preds = %138, %112
%141 = load i64, i64* %2
ret i64 %141
}

LLVM IR (-O2):
define i64 @nibble_sort_word_payer(i64 %0) {
%2 = shl i64 %0, 2
%3 = and i64 %2, 60
%4 = shl nuw nsw i64 1, %3
%5 = lshr i64 %0, 2
%6 = and i64 %5, 60
%7 = shl nuw nsw i64 1, %6
%8 = add nuw nsw i64 %4, %7
%9 = lshr i64 %0, 6
%10 = and i64 %9, 60
%11 = shl nuw nsw i64 1, %10
%12 = add nuw nsw i64 %8, %11
%13 = lshr i64 %0, 10
%14 = and i64 %13, 60
%15 = shl nuw nsw i64 1, %14
%16 = add nuw nsw i64 %12, %15
%17 = lshr i64 %0, 14
%18 = and i64 %17, 60
%19 = shl nuw nsw i64 1, %18
%20 = add nuw nsw i64 %16, %19
%21 = lshr i64 %0, 18
%22 = and i64 %21, 60
%23 = shl nuw nsw i64 1, %22
%24 = add nuw nsw i64 %20, %23
%25 = lshr i64 %0, 22
%26 = and i64 %25, 60
%27 = shl nuw nsw i64 1, %26
%28 = add nuw nsw i64 %24, %27
%29 = lshr i64 %0, 26
%30 = and i64 %29, 60
%31 = shl nuw nsw i64 1, %30
%32 = add nuw i64 %28, %31
%33 = lshr i64 %0, 30
%34 = and i64 %33, 60
%35 = shl nuw nsw i64 1, %34
%36 = add nuw i64 %32, %35
%37 = lshr i64 %0, 34
%38 = and i64 %37, 60
%39 = shl nuw nsw i64 1, %38
%40 = add nuw i64 %36, %39
%41 = lshr i64 %0, 38
%42 = and i64 %41, 60
%43 = shl nuw nsw i64 1, %42
%44 = add nuw i64 %40, %43
%45 = lshr i64 %0, 42
%46 = and i64 %45, 60
%47 = shl nuw nsw i64 1, %46
%48 = add nuw i64 %44, %47
%49 = lshr i64 %0, 46
%50 = and i64 %49, 60
%51 = shl nuw nsw i64 1, %50
%52 = add nuw i64 %48, %51
%53 = lshr i64 %0, 50
%54 = and i64 %53, 60
%55 = shl nuw nsw i64 1, %54
%56 = add nuw i64 %52, %55
%57 = lshr i64 %0, 54
%58 = and i64 %57, 60
%59 = shl nuw nsw i64 1, %58
%60 = add nuw i64 %56, %59
%61 = lshr i64 %0, 58
%62 = and i64 %61, 60
%63 = shl nuw nsw i64 1, %62
%64 = add i64 %60, %63
%65 = icmp eq i64 %64, 0
%66 = tail call i64 @llvm.ctpop.i64(i64 %64)
%67 = icmp ult i64 %66, 2
%68 = or i1 %65, %67
br i1 %68, label %89, label %69
69: ; preds = %1, %83
%70 = phi i64 [ %88, %83 ], [ %64, %1 ]
%71 = phi i64 [ %76, %83 ], [ -1152921504606846976, %1 ]
%72 = phi i64 [ %75, %83 ], [ 15, %1 ]
%73 = phi i64 [ %85, %83 ], [ 0, %1 ]
br label %74
74: ; preds = %69, %79
%75 = phi i64 [ %72, %69 ], [ %81, %79 ]
%76 = phi i64 [ %71, %69 ], [ %80, %79 ]
%77 = and i64 %76, %70
%78 = icmp eq i64 %77, 0
br i1 %78, label %79, label %83
79: ; preds = %74
%80 = lshr i64 %76, 4
%81 = add i64 %75, -1
%82 = icmp ult i64 %76, 16
br i1 %82, label %89, label %74
83: ; preds = %74
%84 = shl i64 %73, 4
%85 = or i64 %84, %75
%86 = shl i64 %75, 2
%87 = shl nsw i64 -1, %86
%88 = add i64 %87, %70
br label %69
89: ; preds = %79, %1
%90 = phi i64 [ %0, %1 ], [ %73, %79 ]
ret i64 %90
}