unsigned long long morton_encode(unsigned x, unsigned y) {
  static const unsigned long long B[] = {
      0x5555555555555555ull, 0x3333333333333333ull, 0x0f0f0f0f0f0f0f0full,
      0x00ff00ff00ff00ffull, 0x0000ffff0000ffffull};
  static const unsigned S[] = {1, 2, 4, 8, 16};
  unsigned long long ullx = x;
  unsigned long long ully = y;
  int i;
  for (i = 4; i >= 0; --i) {
    ullx = (ullx | (ullx << S[i])) & B[i];
    ully = (ully | (ully << S[i])) & B[i];
  }
  return ullx | (ully << 1);
}


x86 assembly (clang, -O0):
<morton_encode>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    -0x4(%rbp),%eax
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%eax
mov    %rax,-0x18(%rbp)
movl   $0x4,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jl     119b <morton_encode+0x9b>
mov    -0x10(%rbp),%rax
mov    -0x10(%rbp),%rdx
movslq -0x1c(%rbp),%rsi
lea    0xef4(%rip),%rcx
mov    (%rcx,%rsi,4),%ecx
shl    %cl,%rdx
mov    %rdx,%rcx
or     %rcx,%rax
movslq -0x1c(%rbp),%rdx
lea    0xead(%rip),%rcx
and    (%rcx,%rdx,8),%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x18(%rbp),%rdx
movslq -0x1c(%rbp),%rsi
lea    0xec2(%rip),%rcx
mov    (%rcx,%rsi,4),%ecx
shl    %cl,%rdx
mov    %rdx,%rcx
or     %rcx,%rax
movslq -0x1c(%rbp),%rdx
lea    0xe7b(%rip),%rcx
and    (%rcx,%rdx,8),%rax
mov    %rax,-0x18(%rbp)
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
jmp    111f <morton_encode+0x1f>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%rcx
shl    $0x1,%rcx
or     %rcx,%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<morton_encode>:
mov    %edi,%eax
mov    %esi,%ecx
mov    %rax,%rdx
shl    $0x10,%rdx
or     %rax,%rdx
movabs $0xffff0000ffff,%rax
and    %rax,%rdx
mov    %rcx,%rsi
shl    $0x10,%rsi
or     %rcx,%rsi
and    %rax,%rsi
mov    %rdx,%rax
shl    $0x8,%rax
or     %rdx,%rax
movabs $0xff00ff00ff00ff,%rcx
and    %rcx,%rax
mov    %rsi,%rdx
shl    $0x8,%rdx
or     %rsi,%rdx
and    %rcx,%rdx
mov    %rax,%rcx
shl    $0x4,%rcx
or     %rax,%rcx
movabs $0xf0f0f0f0f0f0f0f,%rax
0f 0f 0f
and    %rax,%rcx
mov    %rdx,%rsi
shl    $0x4,%rsi
or     %rdx,%rsi
and    %rax,%rsi
lea    0x0(,%rcx,4),%rax
or     %rcx,%rax
movabs $0x3333333333333333,%rcx
33 33 33
and    %rcx,%rax
lea    0x0(,%rsi,4),%rdx
or     %rsi,%rdx
and    %rcx,%rdx
lea    (%rax,%rax,1),%rcx
or     %rax,%rcx
movabs $0x5555555555555555,%rsi
55 55 55
and    %rcx,%rsi
lea    0x0(,%rdx,4),%rax
add    %rdx,%rdx
or     %rax,%rdx
movabs $0xaaaaaaaaaaaaaaaa,%rax
aa aa aa
and    %rdx,%rax
or     %rsi,%rax
ret

LLVM IR (-O0):
@morton_encode.B = internal constant [5 x i64] [i64 6148914691236517205, i64 3689348814741910323, i64 1085102592571150095, i64 71777214294589695, i64 281470681808895]
@morton_encode.S = internal constant [5 x i32] [i32 1, i32 2, i32 4, i32 8, i32 16]
define i64 @morton_encode(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i64
%6 = alloca i64
%7 = alloca i32
store i32 %0, i32* %3
store i32 %1, i32* %4
%8 = load i32, i32* %3
%9 = zext i32 %8 to i64
store i64 %9, i64* %5
%10 = load i32, i32* %4
%11 = zext i32 %10 to i64
store i64 %11, i64* %6
store i32 4, i32* %7
br label %12
12: ; preds = %44, %2
%13 = load i32, i32* %7
%14 = icmp sge i32 %13, 0
br i1 %14, label %15, label %47
15: ; preds = %12
%16 = load i64, i64* %5
%17 = load i64, i64* %5
%18 = load i32, i32* %7
%19 = sext i32 %18 to i64
%20 = getelementptr inbounds [5 x i32], [5 x i32]* @morton_encode.S, i64 0, i64 %19
%21 = load i32, i32* %20
%22 = zext i32 %21 to i64
%23 = shl i64 %17, %22
%24 = or i64 %16, %23
%25 = load i32, i32* %7
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds [5 x i64], [5 x i64]* @morton_encode.B, i64 0, i64 %26
%28 = load i64, i64* %27
%29 = and i64 %24, %28
store i64 %29, i64* %5
%30 = load i64, i64* %6
%31 = load i64, i64* %6
%32 = load i32, i32* %7
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [5 x i32], [5 x i32]* @morton_encode.S, i64 0, i64 %33
%35 = load i32, i32* %34
%36 = zext i32 %35 to i64
%37 = shl i64 %31, %36
%38 = or i64 %30, %37
%39 = load i32, i32* %7
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds [5 x i64], [5 x i64]* @morton_encode.B, i64 0, i64 %40
%42 = load i64, i64* %41
%43 = and i64 %38, %42
store i64 %43, i64* %6
br label %44
44: ; preds = %15
%45 = load i32, i32* %7
%46 = add nsw i32 %45, -1
store i32 %46, i32* %7
br label %12
47: ; preds = %12
%48 = load i64, i64* %5
%49 = load i64, i64* %6
%50 = shl i64 %49, 1
%51 = or i64 %48, %50
ret i64 %51
}

LLVM IR (-O2):
define i64 @morton_encode(i32 %0, i32 %1) {
%3 = zext i32 %0 to i64
%4 = zext i32 %1 to i64
%5 = shl nuw nsw i64 %3, 16
%6 = or i64 %5, %3
%7 = and i64 %6, 281470681808895
%8 = shl nuw nsw i64 %4, 16
%9 = or i64 %8, %4
%10 = and i64 %9, 281470681808895
%11 = shl nuw nsw i64 %7, 8
%12 = or i64 %11, %7
%13 = and i64 %12, 71777214294589695
%14 = shl nuw nsw i64 %10, 8
%15 = or i64 %14, %10
%16 = and i64 %15, 71777214294589695
%17 = shl nuw nsw i64 %13, 4
%18 = or i64 %17, %13
%19 = and i64 %18, 1085102592571150095
%20 = shl nuw nsw i64 %16, 4
%21 = or i64 %20, %16
%22 = and i64 %21, 1085102592571150095
%23 = shl nuw nsw i64 %19, 2
%24 = or i64 %23, %19
%25 = and i64 %24, 3689348814741910323
%26 = shl nuw nsw i64 %22, 2
%27 = or i64 %26, %22
%28 = and i64 %27, 3689348814741910323
%29 = shl nuw nsw i64 %25, 1
%30 = or i64 %29, %25
%31 = and i64 %30, 6148914691236517205
%32 = shl nuw i64 %28, 2
%33 = shl nuw nsw i64 %28, 1
%34 = or i64 %32, %33
%35 = and i64 %34, -6148914691236517206
%36 = or i64 %35, %31
ret i64 %36
}