unsigned long poweroftwo(unsigned long n) {
  unsigned char l;
  if ((n == 0) || ((n & (n - 1)) == 0))
    return n;
  for (l = 0; n > 0; l++, n >>= 1)
    ;
  return (unsigned long)(2 << (l - 1));
}


x86 assembly (clang, -O0):
<poweroftwo>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
cmpq   $0x0,-0x10(%rbp)
je     112c <poweroftwo+0x2c>
mov    -0x10(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    $0x1,%rcx
and    %rcx,%rax
cmp    $0x0,%rax
jne    1139 <poweroftwo+0x39>
mov    -0x10(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    117a <poweroftwo+0x7a>
movb   $0x0,-0x11(%rbp)
cmpq   $0x0,-0x10(%rbp)
jbe    1166 <poweroftwo+0x66>
jmp    114d <poweroftwo+0x4d>
mov    -0x11(%rbp),%al
add    $0x1,%al
mov    %al,-0x11(%rbp)
mov    -0x10(%rbp),%rax
shr    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    113d <poweroftwo+0x3d>
movzbl -0x11(%rbp),%ecx
sub    $0x1,%ecx
mov    $0x2,%eax
shl    %cl,%eax
cltq
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<poweroftwo>:
mov    %rdi,%rax
test   %rdi,%rdi
je     1198 <poweroftwo+0x98>
mov    %rax,%rcx
shr    %rcx
movabs $0x5555555555555555,%rdx
55 55 55
and    %rcx,%rdx
mov    %rax,%rcx
sub    %rdx,%rcx
movabs $0x3333333333333333,%rdx
33 33 33
mov    %rcx,%rsi
and    %rdx,%rsi
shr    $0x2,%rcx
and    %rdx,%rcx
add    %rsi,%rcx
mov    %rcx,%rdx
shr    $0x4,%rdx
add    %rcx,%rdx
movabs $0xf0f0f0f0f0f0f0f,%rcx
0f 0f 0f
and    %rdx,%rcx
movabs $0x101010101010101,%rdx
01 01 01
imul   %rcx,%rdx
shr    $0x38,%rdx
cmp    $0x2,%edx
jb     1198 <poweroftwo+0x98>
mov    $0xffffffff,%ecx
mov    %rax,%rdx
cs nopw 0x0(%rax,%rax,1)
nop
shr    %rdx
add    $0x1,%ecx
cmp    $0x1,%rax
mov    %rdx,%rax
ja     1180 <poweroftwo+0x80>
mov    $0x2,%eax
shl    %cl,%eax
cltq
ret

LLVM IR (-O0):
define i64 @poweroftwo(i64 %0) {
%2 = alloca i64
%3 = alloca i64
%4 = alloca i8
store i64 %0, i64* %3
%5 = load i64, i64* %3
%6 = icmp eq i64 %5, 0
br i1 %6, label %13, label %7
7: ; preds = %1
%8 = load i64, i64* %3
%9 = load i64, i64* %3
%10 = sub i64 %9, 1
%11 = and i64 %8, %10
%12 = icmp eq i64 %11, 0
br i1 %12, label %13, label %15
13: ; preds = %7, %1
%14 = load i64, i64* %3
store i64 %14, i64* %2
br label %31
15: ; preds = %7
store i8 0, i8* %4
br label %16
16: ; preds = %20, %15
%17 = load i64, i64* %3
%18 = icmp ugt i64 %17, 0
br i1 %18, label %19, label %25
19: ; preds = %16
br label %20
20: ; preds = %19
%21 = load i8, i8* %4
%22 = add i8 %21, 1
store i8 %22, i8* %4
%23 = load i64, i64* %3
%24 = lshr i64 %23, 1
store i64 %24, i64* %3
br label %16
25: ; preds = %16
%26 = load i8, i8* %4
%27 = zext i8 %26 to i32
%28 = sub nsw i32 %27, 1
%29 = shl i32 2, %28
%30 = sext i32 %29 to i64
store i64 %30, i64* %2
br label %31
31: ; preds = %25, %13
%32 = load i64, i64* %2
ret i64 %32
}

LLVM IR (-O2):
define i64 @poweroftwo(i64 %0) {
%2 = icmp eq i64 %0, 0
%3 = tail call i64 @llvm.ctpop.i64(i64 %0)
%4 = icmp ult i64 %3, 2
%5 = or i1 %2, %4
br i1 %5, label %16, label %6
6: ; preds = %1, %6
%7 = phi i8 [ %9, %6 ], [ 0, %1 ]
%8 = phi i64 [ %10, %6 ], [ %0, %1 ]
%9 = add nuw nsw i8 %7, 1
%10 = lshr i64 %8, 1
%11 = icmp ult i64 %8, 2
br i1 %11, label %12, label %6
12: ; preds = %6
%13 = zext i8 %7 to i32
%14 = shl i32 2, %13
%15 = sext i32 %14 to i64
br label %16
16: ; preds = %1, %12
%17 = phi i64 [ %15, %12 ], [ %0, %1 ]
ret i64 %17
}