char guess_number(char *p) {
  char type = 0;
  switch (*p++) {
  case '0':
    type = 1;
    break;
  case '1' ... '9':
    type = 4;
    break;
  case 'a' ... 'f':
  case 'A' ... 'F':
    type = 8;
    break;
  }
  while (isxdigit(*p)) {
    switch (*p) {
    case '2' ... '7':
      if (type == 1)
        type = 2;
      break;
    case '8' ... '9':
      type |= 4;
      break;
    case 'a' ... 'f':
    case 'A' ... 'F':
      type |= 8;
      break;
    }
    p++;
  }
  if (type & 8)
    type = 'h';
  else if (type & 4)
    type = 'd';
  else if (type & 2)
    type = 'o';
  else if (type & 1)
    type = 'b';
  return type;
}


x86 assembly (clang, -O0):
<guess_number>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
movb   $0x0,-0x9(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
movsbl (%rax),%eax
add    $0xffffffd0,%eax
mov    %eax,%ecx
mov    %rcx,-0x18(%rbp)
sub    $0x36,%eax
ja     1173 <guess_number+0x63>
mov    -0x18(%rbp),%rax
lea    0xeb1(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
movb   $0x1,-0x9(%rbp)
jmp    1173 <guess_number+0x63>
movb   $0x4,-0x9(%rbp)
jmp    1173 <guess_number+0x63>
jmp    116f <guess_number+0x5f>
movb   $0x8,-0x9(%rbp)
jmp    1178 <guess_number+0x68>
mov    -0x8(%rbp),%rax
movsbl (%rax),%edi
call   1030 <isxdigit@plt>
cmp    $0x0,%eax
je     11ff <guess_number+0xef>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
add    $0xffffffce,%eax
mov    %eax,%ecx
mov    %rcx,-0x20(%rbp)
sub    $0x34,%eax
ja     11ee <guess_number+0xde>
mov    -0x20(%rbp),%rax
lea    0xf2b(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
movsbl -0x9(%rbp),%eax
cmp    $0x1,%eax
jne    11cb <guess_number+0xbb>
movb   $0x2,-0x9(%rbp)
jmp    11ee <guess_number+0xde>
movsbl -0x9(%rbp),%eax
or     $0x4,%eax
mov    %al,-0x9(%rbp)
jmp    11ee <guess_number+0xde>
jmp    11e4 <guess_number+0xd4>
movsbl -0x9(%rbp),%eax
or     $0x8,%eax
mov    %al,-0x9(%rbp)
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    1178 <guess_number+0x68>
movsbl -0x9(%rbp),%eax
and    $0x8,%eax
cmp    $0x0,%eax
je     1218 <guess_number+0x108>
movb   $0x68,-0x9(%rbp)
jmp    126d <guess_number+0x15d>
movsbl -0x9(%rbp),%eax
and    $0x4,%eax
cmp    $0x0,%eax
je     1231 <guess_number+0x121>
movb   $0x64,-0x9(%rbp)
jmp    1268 <guess_number+0x158>
movsbl -0x9(%rbp),%eax
and    $0x2,%eax
cmp    $0x0,%eax
je     124a <guess_number+0x13a>
movb   $0x6f,-0x9(%rbp)
jmp    1263 <guess_number+0x153>
movsbl -0x9(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     125e <guess_number+0x14e>
movb   $0x62,-0x9(%rbp)
jmp    1263 <guess_number+0x153>
jmp    1268 <guess_number+0x158>
jmp    126d <guess_number+0x15d>
movsbl -0x9(%rbp),%eax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<guess_number>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %rdi,%r14
movsbq (%rdi),%rax
add    $0xffffffffffffffd0,%rax
cmp    $0x36,%eax
ja     1138 <guess_number+0x28>
lea    0xece(%rip),%rcx
mov    (%rax,%rcx,1),%bpl
jmp    113a <guess_number+0x2a>
xor    %ebp,%ebp
movsbl 0x1(%r14),%ebx
mov    %ebx,%edi
call   1030 <isxdigit@plt>
test   %eax,%eax
je     11ba <guess_number+0xaa>
add    $0x2,%r14
movabs $0x1f8000001f8000,%r15
mov    $0x3f,%r12d
mov    $0x2,%r13d
jmp    1187 <guess_number+0x77>
cs nopw 0x0(%rax,%rax,1)
or     $0x8,%bpl
movsbl (%r14),%ebx
mov    %ebx,%edi
call   1030 <isxdigit@plt>
add    $0x1,%r14
test   %eax,%eax
je     11ba <guess_number+0xaa>
add    $0xffffffce,%ebx
cmp    $0x34,%ebx
ja     1174 <guess_number+0x64>
bt     %rbx,%r15
jb     1170 <guess_number+0x60>
bt     %rbx,%r12
jae    11a9 <guess_number+0x99>
cmp    $0x1,%bpl
movzbl %bpl,%ebp
cmove  %r13d,%ebp
jmp    1174 <guess_number+0x64>
mov    $0xc0,%eax
bt     %rbx,%rax
jae    1174 <guess_number+0x64>
or     $0x4,%bpl
jmp    1174 <guess_number+0x64>
mov    $0x68,%al
test   $0x8,%bpl
jne    11e2 <guess_number+0xd2>
mov    $0x64,%al
test   $0x4,%bpl
jne    11e2 <guess_number+0xd2>
mov    $0x6f,%al
test   $0x2,%bpl
jne    11e2 <guess_number+0xd2>
movzbl %bpl,%ecx
test   $0x1,%bpl
mov    $0x62,%eax
cmove  %ecx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define signext i8 @guess_number(i8* %0) {
%2 = alloca i8*
%3 = alloca i8
store i8* %0, i8** %2
store i8 0, i8* %3
%4 = load i8*, i8** %2
%5 = getelementptr inbounds i8, i8* %4, i32 1
store i8* %5, i8** %2
%6 = load i8, i8* %4
%7 = sext i8 %6 to i32
switch i32 %7, label %12 [
i32 48, label %8
i32 49, label %9
i32 50, label %9
i32 51, label %9
i32 52, label %9
i32 53, label %9
i32 54, label %9
i32 55, label %9
i32 56, label %9
i32 57, label %9
i32 65, label %11
i32 66, label %11
i32 67, label %11
i32 68, label %11
i32 69, label %11
i32 70, label %11
i32 97, label %10
i32 98, label %10
i32 99, label %10
i32 100, label %10
i32 101, label %10
i32 102, label %10
]
8: ; preds = %1
store i8 1, i8* %3
br label %12
9: ; preds = %1, %1, %1, %1, %1, %1, %1, %1, %1
store i8 4, i8* %3
br label %12
10: ; preds = %1, %1, %1, %1, %1, %1
br label %11
11: ; preds = %1, %1, %1, %1, %1, %1, %10
store i8 8, i8* %3
br label %12
12: ; preds = %1, %11, %9, %8
br label %13
13: ; preds = %40, %12
%14 = load i8*, i8** %2
%15 = load i8, i8* %14
%16 = sext i8 %15 to i32
%17 = call i32 @isxdigit(i32 %16)
%18 = icmp ne i32 %17, 0
br i1 %18, label %19, label %43
19: ; preds = %13
%20 = load i8*, i8** %2
%21 = load i8, i8* %20
%22 = sext i8 %21 to i32
switch i32 %22, label %40 [
i32 50, label %23
i32 51, label %23
i32 52, label %23
i32 53, label %23
i32 54, label %23
i32 55, label %23
i32 56, label %29
i32 57, label %29
i32 65, label %35
i32 66, label %35
i32 67, label %35
i32 68, label %35
i32 69, label %35
i32 70, label %35
i32 97, label %34
i32 98, label %34
i32 99, label %34
i32 100, label %34
i32 101, label %34
i32 102, label %34
]
23: ; preds = %19, %19, %19, %19, %19, %19
%24 = load i8, i8* %3
%25 = sext i8 %24 to i32
%26 = icmp eq i32 %25, 1
br i1 %26, label %27, label %28
27: ; preds = %23
store i8 2, i8* %3
br label %28
28: ; preds = %27, %23
br label %40
29: ; preds = %19, %19
%30 = load i8, i8* %3
%31 = sext i8 %30 to i32
%32 = or i32 %31, 4
%33 = trunc i32 %32 to i8
store i8 %33, i8* %3
br label %40
34: ; preds = %19, %19, %19, %19, %19, %19
br label %35
35: ; preds = %19, %19, %19, %19, %19, %19, %34
%36 = load i8, i8* %3
%37 = sext i8 %36 to i32
%38 = or i32 %37, 8
%39 = trunc i32 %38 to i8
store i8 %39, i8* %3
br label %40
40: ; preds = %19, %35, %29, %28
%41 = load i8*, i8** %2
%42 = getelementptr inbounds i8, i8* %41, i32 1
store i8* %42, i8** %2
br label %13
43: ; preds = %13
%44 = load i8, i8* %3
%45 = sext i8 %44 to i32
%46 = and i32 %45, 8
%47 = icmp ne i32 %46, 0
br i1 %47, label %48, label %49
48: ; preds = %43
store i8 104, i8* %3
br label %70
49: ; preds = %43
%50 = load i8, i8* %3
%51 = sext i8 %50 to i32
%52 = and i32 %51, 4
%53 = icmp ne i32 %52, 0
br i1 %53, label %54, label %55
54: ; preds = %49
store i8 100, i8* %3
br label %69
55: ; preds = %49
%56 = load i8, i8* %3
%57 = sext i8 %56 to i32
%58 = and i32 %57, 2
%59 = icmp ne i32 %58, 0
br i1 %59, label %60, label %61
60: ; preds = %55
store i8 111, i8* %3
br label %68
61: ; preds = %55
%62 = load i8, i8* %3
%63 = sext i8 %62 to i32
%64 = and i32 %63, 1
%65 = icmp ne i32 %64, 0
br i1 %65, label %66, label %67
66: ; preds = %61
store i8 98, i8* %3
br label %67
67: ; preds = %66, %61
br label %68
68: ; preds = %67, %60
br label %69
69: ; preds = %68, %54
br label %70
70: ; preds = %69, %48
%71 = load i8, i8* %3
ret i8 %71
}

LLVM IR (-O2):
@switch.table.guess_number = [55 x i8] c"\01\04\04\04\04\04\04\04\04\04\00\00\00\00\00\00\00\08\08\08\08\08\08\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\08\08\08\08\08\08"
define signext i8 @guess_number(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = sext i8 %2 to i32
%4 = add nsw i32 %3, -48
%5 = icmp ult i32 %4, 55
br i1 %5, label %6, label %10
6: ; preds = %1
%7 = sext i32 %4 to i64
%8 = getelementptr inbounds [55 x i8], [55 x i8]* @switch.table.guess_number, i64 0, i64 %7
%9 = load i8, i8* %8
br label %10
10: ; preds = %6, %1
%11 = phi i8 [ 0, %1 ], [ %9, %6 ]
%12 = getelementptr inbounds i8, i8* %0, i64 1
%13 = load i8, i8* %12
%14 = sext i8 %13 to i32
%15 = tail call i32 @isxdigit(i32 %14)
%16 = icmp eq i32 %15, 0
br i1 %16, label %35, label %17
17: ; preds = %10, %28
%18 = phi i32 [ %32, %28 ], [ %14, %10 ]
%19 = phi i8* [ %30, %28 ], [ %12, %10 ]
%20 = phi i8 [ %29, %28 ], [ %11, %10 ]
switch i32 %18, label %28 [
i32 50, label %21
i32 51, label %21
i32 52, label %21
i32 53, label %21
i32 54, label %21
i32 55, label %21
i32 56, label %24
i32 57, label %24
i32 65, label %26
i32 66, label %26
i32 67, label %26
i32 68, label %26
i32 69, label %26
i32 70, label %26
i32 97, label %26
i32 98, label %26
i32 99, label %26
i32 100, label %26
i32 101, label %26
i32 102, label %26
]
21: ; preds = %17, %17, %17, %17, %17, %17
%22 = icmp eq i8 %20, 1
%23 = select i1 %22, i8 2, i8 %20
br label %28
24: ; preds = %17, %17
%25 = or i8 %20, 4
br label %28
26: ; preds = %17, %17, %17, %17, %17, %17, %17, %17, %17, %17, %17, %17
%27 = or i8 %20, 8
br label %28
28: ; preds = %21, %17, %26, %24
%29 = phi i8 [ %20, %17 ], [ %27, %26 ], [ %25, %24 ], [ %23, %21 ]
%30 = getelementptr inbounds i8, i8* %19, i64 1
%31 = load i8, i8* %30
%32 = sext i8 %31 to i32
%33 = tail call i32 @isxdigit(i32 %32)
%34 = icmp eq i32 %33, 0
br i1 %34, label %35, label %17
35: ; preds = %28, %10
%36 = phi i8 [ %11, %10 ], [ %29, %28 ]
%37 = zext i8 %36 to i32
%38 = and i32 %37, 8
%39 = icmp eq i32 %38, 0
br i1 %39, label %40, label %50
40: ; preds = %35
%41 = and i32 %37, 4
%42 = icmp eq i32 %41, 0
br i1 %42, label %43, label %50
43: ; preds = %40
%44 = and i32 %37, 2
%45 = icmp eq i32 %44, 0
br i1 %45, label %46, label %50
46: ; preds = %43
%47 = and i32 %37, 1
%48 = icmp eq i32 %47, 0
%49 = select i1 %48, i8 %36, i8 98
br label %50
50: ; preds = %46, %43, %40, %35
%51 = phi i8 [ 104, %35 ], [ 100, %40 ], [ 111, %43 ], [ %49, %46 ]
ret i8 %51
}