unsigned int nlz_int128(unsigned __int128 x) {
  unsigned __int128 y;
  unsigned int n = 128;
  y = x >> 64;
  if (y) {
    n -= 64;
    x = y;
  }
  y = x >> 32;
  if (y) {
    n -= 32;
    x = y;
  }
  y = x >> 16;
  if (y) {
    n -= 16;
    x = y;
  }
  y = x >> 8;
  if (y) {
    n -= 8;
    x = y;
  }
  y = x >> 4;
  if (y) {
    n -= 4;
    x = y;
  }
  y = x >> 2;
  if (y) {
    n -= 2;
    x = y;
  }
  y = x >> 1;
  if (y) {
    return n - 2;
  }
  return (unsigned int)(n - x);
}


x86 assembly (clang, -O0):
<nlz_int128>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x20(%rbp)
mov    %rsi,-0x18(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x18(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
movl   $0x80,-0x44(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,-0x40(%rbp)
movq   $0x0,-0x38(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     1162 <nlz_int128+0x62>
jmp    1149 <nlz_int128+0x49>
mov    -0x44(%rbp),%eax
add    $0xffffffc0,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x20,%rdx,%rax
shr    $0x20,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     11ad <nlz_int128+0xad>
jmp    1194 <nlz_int128+0x94>
mov    -0x44(%rbp),%eax
add    $0xffffffe0,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x30,%rdx,%rax
shr    $0x10,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     11f8 <nlz_int128+0xf8>
jmp    11df <nlz_int128+0xdf>
mov    -0x44(%rbp),%eax
add    $0xfffffff0,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x38,%rdx,%rax
shr    $0x8,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     1243 <nlz_int128+0x143>
jmp    122a <nlz_int128+0x12a>
mov    -0x44(%rbp),%eax
add    $0xfffffff8,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x3c,%rdx,%rax
shr    $0x4,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     128e <nlz_int128+0x18e>
jmp    1275 <nlz_int128+0x175>
mov    -0x44(%rbp),%eax
add    $0xfffffffc,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x3e,%rdx,%rax
shr    $0x2,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     12d9 <nlz_int128+0x1d9>
jmp    12c0 <nlz_int128+0x1c0>
mov    -0x44(%rbp),%eax
add    $0xfffffffe,%eax
mov    %eax,-0x44(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x28(%rbp),%rcx
mov    %rcx,%rax
shld   $0x3f,%rdx,%rax
shr    %rcx
mov    %rcx,-0x38(%rbp)
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x38(%rbp),%rcx
or     %rcx,%rax
je     1318 <nlz_int128+0x218>
jmp    130a <nlz_int128+0x20a>
mov    -0x44(%rbp),%eax
sub    $0x2,%eax
mov    %eax,-0x4(%rbp)
jmp    1323 <nlz_int128+0x223>
mov    -0x44(%rbp),%eax
mov    -0x30(%rbp),%ecx
sub    %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<nlz_int128>:
xor    %r9d,%r9d
xor    %r10d,%r10d
test   %rsi,%rsi
cmovne %rsi,%rdi
sete   %r10b
cmove  %rsi,%r9
shl    $0x6,%r10d
lea    0x40(%r10),%r8d
mov    %r9,%rdx
shld   $0x20,%rdi,%rdx
mov    %r9,%rax
shr    $0x20,%rax
or     $0x20,%r10d
mov    %rdx,%rsi
or     %rax,%rsi
cmove  %rdi,%rdx
cmove  %r9,%rax
cmove  %r8d,%r10d
mov    %rax,%r9
shld   $0x30,%rdx,%r9
mov    %rax,%rsi
shr    $0x10,%rsi
lea    -0x10(%r10),%r8d
cmp    $0x10000,%rdx
mov    %rax,%rcx
sbb    $0x0,%rcx
cmovb  %rdx,%r9
cmovb  %rax,%rsi
cmovb  %r10d,%r8d
mov    %rsi,%r11
shld   $0x38,%r9,%r11
mov    %rsi,%rdx
shr    $0x8,%rdx
lea    -0x8(%r8),%r10d
cmp    $0x100,%r9
mov    %rsi,%rdi
sbb    $0x0,%rdi
cmovb  %r9,%r11
cmovb  %rsi,%rdx
cmovb  %r8d,%r10d
mov    %rdx,%rsi
shld   $0x3c,%r11,%rsi
mov    %rdx,%rax
shr    $0x4,%rax
lea    -0x4(%r10),%r8d
cmp    $0x10,%r11
mov    %rdx,%rcx
sbb    $0x0,%rcx
cmovb  %r11,%rsi
cmovb  %rdx,%rax
cmovb  %r10d,%r8d
mov    %rax,%rdx
shld   $0x3e,%rsi,%rdx
mov    %rax,%rcx
shr    $0x2,%rcx
lea    -0x2(%r8),%r9d
cmp    $0x4,%rsi
mov    %rax,%rdi
sbb    $0x0,%rdi
cmovb  %rsi,%rdx
cmovb  %rax,%rcx
cmovb  %r8d,%r9d
mov    %edx,%esi
neg    %esi
cmp    $0x2,%rdx
sbb    $0x0,%rcx
mov    $0xfffffffe,%eax
cmovb  %esi,%eax
add    %r9d,%eax
ret

LLVM IR (-O0):
define i32 @nlz_int128(i64 %0, i64 %1) {
%3 = alloca i32
%4 = alloca i128
%5 = alloca i128
%6 = alloca i128
%7 = alloca i32
%8 = bitcast i128* %4 to { i64, i64 }*
%9 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %8, i32 0, i32 0
store i64 %0, i64* %9
%10 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %8, i32 0, i32 1
store i64 %1, i64* %10
%11 = load i128, i128* %4
store i128 %11, i128* %5
store i32 128, i32* %7
%12 = load i128, i128* %5
%13 = lshr i128 %12, 64
store i128 %13, i128* %6
%14 = load i128, i128* %6
%15 = icmp ne i128 %14, 0
br i1 %15, label %16, label %20
16: ; preds = %2
%17 = load i32, i32* %7
%18 = sub i32 %17, 64
store i32 %18, i32* %7
%19 = load i128, i128* %6
store i128 %19, i128* %5
br label %20
20: ; preds = %16, %2
%21 = load i128, i128* %5
%22 = lshr i128 %21, 32
store i128 %22, i128* %6
%23 = load i128, i128* %6
%24 = icmp ne i128 %23, 0
br i1 %24, label %25, label %29
25: ; preds = %20
%26 = load i32, i32* %7
%27 = sub i32 %26, 32
store i32 %27, i32* %7
%28 = load i128, i128* %6
store i128 %28, i128* %5
br label %29
29: ; preds = %25, %20
%30 = load i128, i128* %5
%31 = lshr i128 %30, 16
store i128 %31, i128* %6
%32 = load i128, i128* %6
%33 = icmp ne i128 %32, 0
br i1 %33, label %34, label %38
34: ; preds = %29
%35 = load i32, i32* %7
%36 = sub i32 %35, 16
store i32 %36, i32* %7
%37 = load i128, i128* %6
store i128 %37, i128* %5
br label %38
38: ; preds = %34, %29
%39 = load i128, i128* %5
%40 = lshr i128 %39, 8
store i128 %40, i128* %6
%41 = load i128, i128* %6
%42 = icmp ne i128 %41, 0
br i1 %42, label %43, label %47
43: ; preds = %38
%44 = load i32, i32* %7
%45 = sub i32 %44, 8
store i32 %45, i32* %7
%46 = load i128, i128* %6
store i128 %46, i128* %5
br label %47
47: ; preds = %43, %38
%48 = load i128, i128* %5
%49 = lshr i128 %48, 4
store i128 %49, i128* %6
%50 = load i128, i128* %6
%51 = icmp ne i128 %50, 0
br i1 %51, label %52, label %56
52: ; preds = %47
%53 = load i32, i32* %7
%54 = sub i32 %53, 4
store i32 %54, i32* %7
%55 = load i128, i128* %6
store i128 %55, i128* %5
br label %56
56: ; preds = %52, %47
%57 = load i128, i128* %5
%58 = lshr i128 %57, 2
store i128 %58, i128* %6
%59 = load i128, i128* %6
%60 = icmp ne i128 %59, 0
br i1 %60, label %61, label %65
61: ; preds = %56
%62 = load i32, i32* %7
%63 = sub i32 %62, 2
store i32 %63, i32* %7
%64 = load i128, i128* %6
store i128 %64, i128* %5
br label %65
65: ; preds = %61, %56
%66 = load i128, i128* %5
%67 = lshr i128 %66, 1
store i128 %67, i128* %6
%68 = load i128, i128* %6
%69 = icmp ne i128 %68, 0
br i1 %69, label %70, label %73
70: ; preds = %65
%71 = load i32, i32* %7
%72 = sub i32 %71, 2
store i32 %72, i32* %3
br label %79
73: ; preds = %65
%74 = load i32, i32* %7
%75 = zext i32 %74 to i128
%76 = load i128, i128* %5
%77 = sub i128 %75, %76
%78 = trunc i128 %77 to i32
store i32 %78, i32* %3
br label %79
79: ; preds = %73, %70
%80 = load i32, i32* %3
ret i32 %80
}

LLVM IR (-O2):
define i32 @nlz_int128(i64 %0, i64 %1) {
%3 = zext i64 %1 to i128
%4 = shl nuw i128 %3, 64
%5 = zext i64 %0 to i128
%6 = or i128 %4, %5
%7 = icmp eq i64 %1, 0
%8 = select i1 %7, i128 %6, i128 %3
%9 = select i1 %7, i32 128, i32 64
%10 = icmp ult i128 %8, 4294967296
%11 = lshr i128 %8, 32
%12 = add nsw i32 %9, -32
%13 = select i1 %10, i128 %8, i128 %11
%14 = select i1 %10, i32 %9, i32 %12
%15 = icmp ult i128 %13, 65536
%16 = lshr i128 %13, 16
%17 = add nsw i32 %14, -16
%18 = select i1 %15, i128 %13, i128 %16
%19 = select i1 %15, i32 %14, i32 %17
%20 = icmp ult i128 %18, 256
%21 = lshr i128 %18, 8
%22 = add nsw i32 %19, -8
%23 = select i1 %20, i128 %18, i128 %21
%24 = select i1 %20, i32 %19, i32 %22
%25 = icmp ult i128 %23, 16
%26 = lshr i128 %23, 4
%27 = add nsw i32 %24, -4
%28 = select i1 %25, i128 %23, i128 %26
%29 = select i1 %25, i32 %24, i32 %27
%30 = icmp ult i128 %28, 4
%31 = lshr i128 %28, 2
%32 = add nsw i32 %29, -2
%33 = select i1 %30, i128 %28, i128 %31
%34 = select i1 %30, i32 %29, i32 %32
%35 = icmp ult i128 %33, 2
%36 = trunc i128 %33 to i32
%37 = sub i32 0, %36
%38 = select i1 %35, i32 %37, i32 -2
%39 = add i32 %38, %34
ret i32 %39
}