unsigned long higher_prime_number(unsigned long n) {
  static const unsigned long primes[] = {
      (unsigned long)7,
      (unsigned long)13,
      (unsigned long)31,
      (unsigned long)61,
      (unsigned long)127,
      (unsigned long)251,
      (unsigned long)509,
      (unsigned long)1021,
      (unsigned long)2039,
      (unsigned long)4093,
      (unsigned long)8191,
      (unsigned long)16381,
      (unsigned long)32749,
      (unsigned long)65521,
      (unsigned long)131071,
      (unsigned long)262139,
      (unsigned long)524287,
      (unsigned long)1048573,
      (unsigned long)2097143,
      (unsigned long)4194301,
      (unsigned long)8388593,
      (unsigned long)16777213,
      (unsigned long)33554393,
      (unsigned long)67108859,
      (unsigned long)134217689,
      (unsigned long)268435399,
      (unsigned long)536870909,
      (unsigned long)1073741789,
      (unsigned long)2147483647,
      ((unsigned long)2147483647) + ((unsigned long)2147483644),
  };
  const unsigned long *low = &primes[0];
  const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
  while (low != high) {
    const unsigned long *mid = low + (high - low) / 2;
    if (n > *mid)
      low = mid + 1;
    else
      high = mid;
  }
  return *low;
}


x86 assembly (clang, -O0):
<higher_prime_number>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
lea    0xef1(%rip),%rax
mov    %rax,-0x10(%rbp)
lea    0xee6(%rip),%rax
add    $0xf0,%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rax
cmp    -0x18(%rbp),%rax
je     1194 <higher_prime_number+0x94>
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    %rcx,%rax
sar    $0x3,%rax
mov    $0x2,%ecx
cqto
idiv   %rcx
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
shl    $0x3,%rcx
add    %rcx,%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rcx
cmp    (%rcx),%rax
jbe    1187 <higher_prime_number+0x87>
mov    -0x20(%rbp),%rax
add    $0x8,%rax
mov    %rax,-0x10(%rbp)
jmp    118f <higher_prime_number+0x8f>
mov    -0x20(%rbp),%rax
mov    %rax,-0x18(%rbp)
jmp    1124 <higher_prime_number+0x24>
mov    -0x10(%rbp),%rax
mov    (%rax),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<higher_prime_number>:
lea    0xfe9(%rip),%rax
lea    0xef2(%rip),%rcx
jmp    1119 <higher_prime_number+0x19>
lea    (%rcx,%rdx,4),%rax
cmp    %rax,%rcx
je     1144 <higher_prime_number+0x44>
mov    %rax,%rdx
sub    %rcx,%rdx
mov    %rdx,%rsi
sar    $0x3,%rsi
shr    $0x3f,%rdx
add    %rsi,%rdx
and    $0xfffffffffffffffe,%rdx
cmp    %rdi,(%rcx,%rdx,4)
jae    1110 <higher_prime_number+0x10>
lea    (%rcx,%rdx,4),%rcx
add    $0x8,%rcx
cmp    %rax,%rcx
jne    1119 <higher_prime_number+0x19>
mov    (%rax),%rax
ret

LLVM IR (-O0):
@higher_prime_number.primes = internal constant [30 x i64] [i64 7, i64 13, i64 31, i64 61, i64 127, i64 251, i64 509, i64 1021, i64 2039, i64 4093, i64 8191, i64 16381, i64 32749, i64 65521, i64 131071, i64 262139, i64 524287, i64 1048573, i64 2097143, i64 4194301, i64 8388593, i64 16777213, i64 33554393, i64 67108859, i64 134217689, i64 268435399, i64 536870909, i64 1073741789, i64 2147483647, i64 4294967291]
define i64 @higher_prime_number(i64 %0) {
%2 = alloca i64
%3 = alloca i64*
%4 = alloca i64*
%5 = alloca i64*
store i64 %0, i64* %2
store i64* getelementptr inbounds ([30 x i64], [30 x i64]* @higher_prime_number.primes, i64 0, i64 0), i64** %3
store i64* getelementptr inbounds ([30 x i64], [30 x i64]* @higher_prime_number.primes, i64 1, i64 0), i64** %4
br label %6
6: ; preds = %29, %1
%7 = load i64*, i64** %3
%8 = load i64*, i64** %4
%9 = icmp ne i64* %7, %8
br i1 %9, label %10, label %30
10: ; preds = %6
%11 = load i64*, i64** %3
%12 = load i64*, i64** %4
%13 = load i64*, i64** %3
%14 = ptrtoint i64* %12 to i64
%15 = ptrtoint i64* %13 to i64
%16 = sub i64 %14, %15
%17 = sdiv exact i64 %16, 8
%18 = sdiv i64 %17, 2
%19 = getelementptr inbounds i64, i64* %11, i64 %18
store i64* %19, i64** %5
%20 = load i64, i64* %2
%21 = load i64*, i64** %5
%22 = load i64, i64* %21
%23 = icmp ugt i64 %20, %22
br i1 %23, label %24, label %27
24: ; preds = %10
%25 = load i64*, i64** %5
%26 = getelementptr inbounds i64, i64* %25, i64 1
store i64* %26, i64** %3
br label %29
27: ; preds = %10
%28 = load i64*, i64** %5
store i64* %28, i64** %4
br label %29
29: ; preds = %27, %24
br label %6
30: ; preds = %6
%31 = load i64*, i64** %3
%32 = load i64, i64* %31
ret i64 %32
}

LLVM IR (-O2):
@higher_prime_number.primes = internal constant [30 x i64] [i64 7, i64 13, i64 31, i64 61, i64 127, i64 251, i64 509, i64 1021, i64 2039, i64 4093, i64 8191, i64 16381, i64 32749, i64 65521, i64 131071, i64 262139, i64 524287, i64 1048573, i64 2097143, i64 4194301, i64 8388593, i64 16777213, i64 33554393, i64 67108859, i64 134217689, i64 268435399, i64 536870909, i64 1073741789, i64 2147483647, i64 4294967291]
define i64 @higher_prime_number(i64 %0) {
br label %2
2: ; preds = %1, %2
%3 = phi i64* [ getelementptr inbounds ([30 x i64], [30 x i64]* @higher_prime_number.primes, i64 0, i64 0), %1 ], [ %15, %2 ]
%4 = phi i64* [ getelementptr inbounds ([30 x i64], [30 x i64]* @higher_prime_number.primes, i64 1, i64 0), %1 ], [ %14, %2 ]
%5 = ptrtoint i64* %4 to i64
%6 = ptrtoint i64* %3 to i64
%7 = sub i64 %5, %6
%8 = ashr exact i64 %7, 3
%9 = sdiv i64 %8, 2
%10 = getelementptr inbounds i64, i64* %3, i64 %9
%11 = load i64, i64* %10
%12 = icmp ult i64 %11, %0
%13 = getelementptr inbounds i64, i64* %10, i64 1
%14 = select i1 %12, i64* %4, i64* %10
%15 = select i1 %12, i64* %13, i64* %3
%16 = icmp eq i64* %15, %14
br i1 %16, label %17, label %2
17: ; preds = %2
%18 = load i64, i64* %14
ret i64 %18
}