char countLeadingZeros32(unsigned long a) {
  static const char countLeadingZerosHigh[] = {
      8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
      3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  char shiftCount;
  shiftCount = 0;
  if (a < 0x10000) {
    shiftCount += 16;
    a <<= 16;
  }
  if (a < 0x1000000) {
    shiftCount += 8;
    a <<= 8;
  }
  shiftCount += countLeadingZerosHigh[a >> 24];
  return shiftCount;
}


x86 assembly (clang, -O0):
<countLeadingZeros32>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movb   $0x0,-0x9(%rbp)
cmpq   $0x10000,-0x8(%rbp)
jae    1130 <countLeadingZeros32+0x30>
movsbl -0x9(%rbp),%eax
add    $0x10,%eax
mov    %al,-0x9(%rbp)
mov    -0x8(%rbp),%rax
shl    $0x10,%rax
mov    %rax,-0x8(%rbp)
cmpq   $0x1000000,-0x8(%rbp)
01
jae    1154 <countLeadingZeros32+0x54>
movsbl -0x9(%rbp),%eax
add    $0x8,%eax
mov    %al,-0x9(%rbp)
mov    -0x8(%rbp),%rax
shl    $0x8,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rcx
shr    $0x18,%rcx
lea    0xe9d(%rip),%rax
movsbl (%rax,%rcx,1),%ecx
movsbl -0x9(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x9(%rbp)
movsbl -0x9(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<countLeadingZeros32>:
mov    %rdi,%rax
shl    $0x10,%rax
cmp    $0x10000,%rdi
setb   %cl
cmovae %rdi,%rax
shl    $0x4,%cl
lea    0x8(%rcx),%edx
mov    %rax,%rsi
shl    $0x8,%rsi
cmp    $0x1000000,%rax
cmovae %rax,%rsi
movzbl %cl,%ecx
movzbl %dl,%eax
cmovae %ecx,%eax
shr    $0x18,%rsi
lea    0xec0(%rip),%rcx
add    (%rsi,%rcx,1),%al
ret

LLVM IR (-O0):
@countLeadingZeros32.countLeadingZerosHigh = internal constant <{ [128 x i8], [128 x i8] }> <{ [128 x i8] c"\08\07\06\06\05\05\05\05\04\04\04\04\04\04\04\04\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01", [128 x i8] zeroinitializer }>
define signext i8 @countLeadingZeros32(i64 %0) {
%2 = alloca i64
%3 = alloca i8
store i64 %0, i64* %2
store i8 0, i8* %3
%4 = load i64, i64* %2
%5 = icmp ult i64 %4, 65536
br i1 %5, label %6, label %13
6: ; preds = %1
%7 = load i8, i8* %3
%8 = sext i8 %7 to i32
%9 = add nsw i32 %8, 16
%10 = trunc i32 %9 to i8
store i8 %10, i8* %3
%11 = load i64, i64* %2
%12 = shl i64 %11, 16
store i64 %12, i64* %2
br label %13
13: ; preds = %6, %1
%14 = load i64, i64* %2
%15 = icmp ult i64 %14, 16777216
br i1 %15, label %16, label %23
16: ; preds = %13
%17 = load i8, i8* %3
%18 = sext i8 %17 to i32
%19 = add nsw i32 %18, 8
%20 = trunc i32 %19 to i8
store i8 %20, i8* %3
%21 = load i64, i64* %2
%22 = shl i64 %21, 8
store i64 %22, i64* %2
br label %23
23: ; preds = %16, %13
%24 = load i64, i64* %2
%25 = lshr i64 %24, 24
%26 = getelementptr inbounds [256 x i8], [256 x i8]* bitcast (<{ [128 x i8], [128 x i8] }>* @countLeadingZeros32.countLeadingZerosHigh to [256 x i8]*), i64 0, i64 %25
%27 = load i8, i8* %26
%28 = sext i8 %27 to i32
%29 = load i8, i8* %3
%30 = sext i8 %29 to i32
%31 = add nsw i32 %30, %28
%32 = trunc i32 %31 to i8
store i8 %32, i8* %3
%33 = load i8, i8* %3
ret i8 %33
}

LLVM IR (-O2):
@countLeadingZeros32.countLeadingZerosHigh = internal unnamed_addr constant <{ [128 x i8], [128 x i8] }> <{ [128 x i8] c"\08\07\06\06\05\05\05\05\04\04\04\04\04\04\04\04\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01", [128 x i8] zeroinitializer }>
define signext i8 @countLeadingZeros32(i64 %0) {
%2 = icmp ult i64 %0, 65536
%3 = shl i64 %0, 16
%4 = select i1 %2, i64 %3, i64 %0
%5 = select i1 %2, i8 16, i8 0
%6 = icmp ult i64 %4, 16777216
%7 = or i8 %5, 8
%8 = shl i64 %4, 8
%9 = select i1 %6, i64 %8, i64 %4
%10 = select i1 %6, i8 %7, i8 %5
%11 = lshr i64 %9, 24
%12 = getelementptr inbounds [256 x i8], [256 x i8]* bitcast (<{ [128 x i8], [128 x i8] }>* @countLeadingZeros32.countLeadingZerosHigh to [256 x i8]*), i64 0, i64 %11
%13 = load i8, i8* %12
%14 = add i8 %13, %10
ret i8 %14
}