#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int uint8_t;
typedef int uint32_t;

/* Variables and functions */
uint8_t ctz(uint32_t x) {
  static const uint8_t bval[] = {4, 0, 1, 0, 2, 0, 1, 0,
                                 3, 0, 1, 0, 2, 0, 1, 0};
  unsigned int r = 0;
  if (x & 0x1) {
    return r;
  }
  if ((x & 0xFFFF) == 0) {
    r += 16;
    x >>= 16;
  }
  if ((x & 0xFF) == 0) {
    r += 8;
    x >>= 8;
  }
  if ((x & 0xF) == 0) {
    r += 4;
    x >>= 4;
  }
  return r + bval[(x & 0x0F)];
}


x86 assembly (clang, -O0):
<ctz>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x8(%rbp)
movl   $0x0,-0xc(%rbp)
mov    -0x8(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1128 <ctz+0x28>
mov    -0xc(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    11a8 <ctz+0xa8>
mov    -0x8(%rbp),%eax
and    $0xffff,%eax
cmp    $0x0,%eax
jne    114b <ctz+0x4b>
mov    -0xc(%rbp),%eax
add    $0x10,%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
sar    $0x10,%eax
mov    %eax,-0x8(%rbp)
mov    -0x8(%rbp),%eax
and    $0xff,%eax
cmp    $0x0,%eax
jne    116e <ctz+0x6e>
mov    -0xc(%rbp),%eax
add    $0x8,%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
sar    $0x8,%eax
mov    %eax,-0x8(%rbp)
mov    -0x8(%rbp),%eax
and    $0xf,%eax
cmp    $0x0,%eax
jne    118f <ctz+0x8f>
mov    -0xc(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
sar    $0x4,%eax
mov    %eax,-0x8(%rbp)
mov    -0xc(%rbp),%eax
mov    -0x8(%rbp),%ecx
and    $0xf,%ecx
movslq %ecx,%rdx
lea    0xe5e(%rip),%rcx
add    (%rcx,%rdx,4),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ctz>:
xor    %eax,%eax
test   $0x1,%dil
jne    114a <ctz+0x4a>
mov    %edi,%eax
sar    $0x10,%eax
xor    %ecx,%ecx
test   %di,%di
sete   %cl
cmovne %edi,%eax
shl    $0x4,%ecx
lea    0x8(%rcx),%edx
mov    %eax,%esi
sar    $0x8,%esi
test   %al,%al
cmovne %eax,%esi
cmovne %ecx,%edx
lea    0x4(%rdx),%eax
mov    %esi,%ecx
shr    $0x4,%ecx
test   $0xf,%sil
cmovne %esi,%ecx
cmovne %edx,%eax
and    $0xf,%ecx
lea    0xeb9(%rip),%rdx
add    (%rdx,%rcx,4),%eax
ret

LLVM IR (-O0):
@ctz.bval = internal constant [16 x i32] [i32 4, i32 0, i32 1, i32 0, i32 2, i32 0, i32 1, i32 0, i32 3, i32 0, i32 1, i32 0, i32 2, i32 0, i32 1, i32 0]
define i32 @ctz(i32 %0) {
%2 = alloca i32
%3 = alloca i32
%4 = alloca i32
store i32 %0, i32* %3
store i32 0, i32* %4
%5 = load i32, i32* %3
%6 = and i32 %5, 1
%7 = icmp ne i32 %6, 0
br i1 %7, label %8, label %10
8: ; preds = %1
%9 = load i32, i32* %4
store i32 %9, i32* %2
br label %45
10: ; preds = %1
%11 = load i32, i32* %3
%12 = and i32 %11, 65535
%13 = icmp eq i32 %12, 0
br i1 %13, label %14, label %19
14: ; preds = %10
%15 = load i32, i32* %4
%16 = add i32 %15, 16
store i32 %16, i32* %4
%17 = load i32, i32* %3
%18 = ashr i32 %17, 16
store i32 %18, i32* %3
br label %19
19: ; preds = %14, %10
%20 = load i32, i32* %3
%21 = and i32 %20, 255
%22 = icmp eq i32 %21, 0
br i1 %22, label %23, label %28
23: ; preds = %19
%24 = load i32, i32* %4
%25 = add i32 %24, 8
store i32 %25, i32* %4
%26 = load i32, i32* %3
%27 = ashr i32 %26, 8
store i32 %27, i32* %3
br label %28
28: ; preds = %23, %19
%29 = load i32, i32* %3
%30 = and i32 %29, 15
%31 = icmp eq i32 %30, 0
br i1 %31, label %32, label %37
32: ; preds = %28
%33 = load i32, i32* %4
%34 = add i32 %33, 4
store i32 %34, i32* %4
%35 = load i32, i32* %3
%36 = ashr i32 %35, 4
store i32 %36, i32* %3
br label %37
37: ; preds = %32, %28
%38 = load i32, i32* %4
%39 = load i32, i32* %3
%40 = and i32 %39, 15
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [16 x i32], [16 x i32]* @ctz.bval, i64 0, i64 %41
%43 = load i32, i32* %42
%44 = add i32 %38, %43
store i32 %44, i32* %2
br label %45
45: ; preds = %37, %8
%46 = load i32, i32* %2
ret i32 %46
}

LLVM IR (-O2):
@ctz.bval = internal unnamed_addr constant [16 x i32] [i32 4, i32 0, i32 1, i32 0, i32 2, i32 0, i32 1, i32 0, i32 3, i32 0, i32 1, i32 0, i32 2, i32 0, i32 1, i32 0]
define i32 @ctz(i32 %0) {
%2 = and i32 %0, 1
%3 = icmp eq i32 %2, 0
br i1 %3, label %4, label %27
4: ; preds = %1
%5 = and i32 %0, 65535
%6 = icmp eq i32 %5, 0
%7 = ashr i32 %0, 16
%8 = select i1 %6, i32 %7, i32 %0
%9 = select i1 %6, i32 16, i32 0
%10 = and i32 %8, 255
%11 = icmp eq i32 %10, 0
%12 = or i32 %9, 8
%13 = ashr i32 %8, 8
%14 = select i1 %11, i32 %13, i32 %8
%15 = select i1 %11, i32 %12, i32 %9
%16 = and i32 %14, 15
%17 = icmp eq i32 %16, 0
%18 = or i32 %15, 4
%19 = lshr i32 %14, 4
%20 = select i1 %17, i32 %19, i32 %14
%21 = select i1 %17, i32 %18, i32 %15
%22 = and i32 %20, 15
%23 = zext i32 %22 to i64
%24 = getelementptr inbounds [16 x i32], [16 x i32]* @ctz.bval, i64 0, i64 %23
%25 = load i32, i32* %24
%26 = add i32 %25, %21
br label %27
27: ; preds = %1, %4
%28 = phi i32 [ %26, %4 ], [ 0, %1 ]
ret i32 %28
}