__attribute__((always_)) long __find_first_zero_bit(const unsigned long *addr,
                                                    unsigned long size) {
  long d0, d1, d2;
  long res;
  size += 63;
  size >>= 6;
  if (!size)
    return 0;
  asm volatile("  repe; scasq\n"
               "  je 1f\n"
               "  xorq -8(%%rdi),%%rax\n"
               "  subq $8,%%rdi\n"
               "  bsfq %%rax,%%rdx\n"
               "1:  subq %[addr],%%rdi\n"
               "  shlq $3,%%rdi\n"
               "  addq %%rdi,%%rdx"
               : "=d"(res), "=&c"(d0), "=&D"(d1), "=&a"(d2)
               : "0"(0ULL), "1"(size), "2"(addr), "3"(-1ULL), [addr] "S"(addr)
               : "memory");
  return res;
}


x86 assembly (clang, -O0):
<__find_first_zero_bit>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    -0x18(%rbp),%rax
add    $0x3f,%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rax
shr    $0x6,%rax
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    113c <__find_first_zero_bit+0x3c>
movq   $0x0,-0x8(%rbp)
jmp    118a <__find_first_zero_bit+0x8a>
mov    -0x18(%rbp),%rcx
mov    -0x10(%rbp),%rdi
mov    -0x10(%rbp),%rsi
xor    %eax,%eax
mov    %eax,%edx
mov    $0xffffffffffffffff,%rax
repz scas %es:(%rdi),%rax
je     1168 <__find_first_zero_bit+0x68>
xor    -0x8(%rdi),%rax
sub    $0x8,%rdi
bsf    %rax,%rdx
sub    %rsi,%rdi
shl    $0x3,%rdi
add    %rdi,%rdx
mov    %rdx,-0x38(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %rdi,-0x28(%rbp)
mov    %rax,-0x30(%rbp)
mov    -0x38(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<__find_first_zero_bit>:
mov    %rsi,%rcx
add    $0x3f,%rcx
cmp    $0x40,%rcx
jae    1110 <__find_first_zero_bit+0x10>
xor    %eax,%eax
ret
shr    $0x6,%rcx
mov    %rdi,%rsi
mov    $0xffffffffffffffff,%rax
xor    %edx,%edx
repz scas %es:(%rdi),%rax
je     1131 <__find_first_zero_bit+0x31>
xor    -0x8(%rdi),%rax
sub    $0x8,%rdi
bsf    %rax,%rdx
sub    %rsi,%rdi
shl    $0x3,%rdi
add    %rdi,%rdx
mov    %rdx,%rax
ret

LLVM IR (-O0):
define i64 @__find_first_zero_bit(i64* %0, i64 %1) {
%3 = alloca i64
%4 = alloca i64*
%5 = alloca i64
%6 = alloca i64
%7 = alloca i64
%8 = alloca i64
%9 = alloca i64
store i64* %0, i64** %4
store i64 %1, i64* %5
%10 = load i64, i64* %5
%11 = add i64 %10, 63
store i64 %11, i64* %5
%12 = load i64, i64* %5
%13 = lshr i64 %12, 6
store i64 %13, i64* %5
%14 = load i64, i64* %5
%15 = icmp ne i64 %14, 0
br i1 %15, label %17, label %16
16: ; preds = %2
store i64 0, i64* %3
br label %27
17: ; preds = %2
%18 = load i64, i64* %5
%19 = load i64*, i64** %4
%20 = load i64*, i64** %4
%21 = call { i64, i64, i64, i64 } asm sideeffect " repe; scasq\0A je 1f\0A xorq -8(%rdi),%rax\0A subq $$8,%rdi\0A bsfq %rax,%rdx\0A1: subq $8,%rdi\0A shlq $$3,%rdi\0A addq %rdi,%rdx", "={dx},=&{cx},=&{di},=&{ax},0,1,2,3,{si},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 0, i64 %18, i64* %19, i64 -1, i64* %20)
%22 = extractvalue { i64, i64, i64, i64 } %21, 0
%23 = extractvalue { i64, i64, i64, i64 } %21, 1
%24 = extractvalue { i64, i64, i64, i64 } %21, 2
%25 = extractvalue { i64, i64, i64, i64 } %21, 3
store i64 %22, i64* %9
store i64 %23, i64* %6
store i64 %24, i64* %7
store i64 %25, i64* %8
%26 = load i64, i64* %9
store i64 %26, i64* %3
br label %27
27: ; preds = %17, %16
%28 = load i64, i64* %3
ret i64 %28
}

LLVM IR (-O2):
define i64 @__find_first_zero_bit(i64* %0, i64 %1) {
%3 = add i64 %1, 63
%4 = icmp ult i64 %3, 64
br i1 %4, label %9, label %5
5: ; preds = %2
%6 = lshr i64 %3, 6
%7 = tail call { i64, i64, i64, i64 } asm sideeffect " repe; scasq\0A je 1f\0A xorq -8(%rdi),%rax\0A subq $$8,%rdi\0A bsfq %rax,%rdx\0A1: subq $8,%rdi\0A shlq $$3,%rdi\0A addq %rdi,%rdx", "={dx},=&{cx},=&{di},=&{ax},0,1,2,3,{si},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 0, i64 %6, i64* %0, i64 -1, i64* %0)
%8 = extractvalue { i64, i64, i64, i64 } %7, 0
br label %9
9: ; preds = %2, %5
%10 = phi i64 [ %8, %5 ], [ 0, %2 ]
ret i64 %10
}