unsigned char encode_5bit(unsigned char c) {
  unsigned char map[] = {0xFF, 0x0A, 0x0B, 0x0C, 0xFF, 0x0D, 0x0E, 0x0F, 0xFF,
                         0x10, 0x11, 0x12, 0x13, 0x14, 0xFF, 0x15, 0x16, 0x17,
                         0x18, 0x19, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E};
  if (c >= '0' && c <= '9')
    return c - '0';
  else if (c >= 'A' && c <= 'Z')
    return map[c - 'A'];
  else
    return 0xFF;
}


x86 assembly (clang, -O0):
<encode_5bit>:
push   %rbp
mov    %rsp,%rbp
mov    %dil,%al
mov    %al,-0x2(%rbp)
mov    0xeef(%rip),%rax
mov    %rax,-0x20(%rbp)
mov    0xeec(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    0xee9(%rip),%rax
mov    %rax,-0x10(%rbp)
mov    0xee6(%rip),%ax
mov    %ax,-0x8(%rbp)
movzbl -0x2(%rbp),%eax
cmp    $0x30,%eax
jl     115f <encode_5bit+0x5f>
movzbl -0x2(%rbp),%eax
cmp    $0x39,%eax
jg     115f <encode_5bit+0x5f>
movzbl -0x2(%rbp),%eax
sub    $0x30,%eax
mov    %al,-0x1(%rbp)
jmp    1192 <encode_5bit+0x92>
movzbl -0x2(%rbp),%eax
cmp    $0x41,%eax
jl     118e <encode_5bit+0x8e>
movzbl -0x2(%rbp),%eax
cmp    $0x5a,%eax
jg     118e <encode_5bit+0x8e>
movzbl -0x2(%rbp),%eax
sub    $0x41,%eax
cltq
mov    -0x20(%rbp,%rax,1),%al
mov    %al,-0x1(%rbp)
jmp    1192 <encode_5bit+0x92>
movb   $0xff,-0x1(%rbp)
movzbl -0x1(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<encode_5bit>:
lea    -0x30(%rdi),%eax
cmp    $0xa,%al
jb     1120 <encode_5bit+0x20>
lea    -0x41(%rdi),%ecx
mov    $0xff,%al
cmp    $0x19,%cl
ja     1120 <encode_5bit+0x20>
mov    %edi,%eax
add    $0xffffffbf,%eax
lea    0xee3(%rip),%rcx
mov    (%rax,%rcx,1),%al
ret

LLVM IR (-O0):
@__const.encode_5bit.map = [26 x i8] c"\FF\0A\0B\0C\FF\0D\0E\0F\FF\10\11\12\13\14\FF\15\16\17\18\19\FF\1A\1B\1C\1D\1E"
define zeroext i8 @encode_5bit(i8 zeroext %0) {
%2 = alloca i8
%3 = alloca i8
%4 = alloca [26 x i8]
store i8 %0, i8* %3
%5 = bitcast [26 x i8]* %4 to i8*
%6 = load i8, i8* %3
%7 = zext i8 %6 to i32
%8 = icmp sge i32 %7, 48
br i1 %8, label %9, label %18
9: ; preds = %1
%10 = load i8, i8* %3
%11 = zext i8 %10 to i32
%12 = icmp sle i32 %11, 57
br i1 %12, label %13, label %18
13: ; preds = %9
%14 = load i8, i8* %3
%15 = zext i8 %14 to i32
%16 = sub nsw i32 %15, 48
%17 = trunc i32 %16 to i8
store i8 %17, i8* %2
br label %34
18: ; preds = %9, %1
%19 = load i8, i8* %3
%20 = zext i8 %19 to i32
%21 = icmp sge i32 %20, 65
br i1 %21, label %22, label %33
22: ; preds = %18
%23 = load i8, i8* %3
%24 = zext i8 %23 to i32
%25 = icmp sle i32 %24, 90
br i1 %25, label %26, label %33
26: ; preds = %22
%27 = load i8, i8* %3
%28 = zext i8 %27 to i32
%29 = sub nsw i32 %28, 65
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds [26 x i8], [26 x i8]* %4, i64 0, i64 %30
%32 = load i8, i8* %31
store i8 %32, i8* %2
br label %34
33: ; preds = %22, %18
store i8 -1, i8* %2
br label %34
34: ; preds = %33, %26, %13
%35 = load i8, i8* %2
ret i8 %35
}

LLVM IR (-O2):
@__const.encode_5bit.map = [26 x i8] c"\FF\0A\0B\0C\FF\0D\0E\0F\FF\10\11\12\13\14\FF\15\16\17\18\19\FF\1A\1B\1C\1D\1E"
define zeroext i8 @encode_5bit(i8 zeroext %0) {
%2 = zext i8 %0 to i64
%3 = add i8 %0, -48
%4 = icmp ult i8 %3, 10
br i1 %4, label %13, label %5
5: ; preds = %1
%6 = add i8 %0, -65
%7 = icmp ult i8 %6, 26
br i1 %7, label %8, label %13
8: ; preds = %5
%9 = add nuw nsw i64 %2, 4294967231
%10 = and i64 %9, 4294967295
%11 = getelementptr inbounds [26 x i8], [26 x i8]* @__const.encode_5bit.map, i64 0, i64 %10
%12 = load i8, i8* %11
br label %13
13: ; preds = %1, %5, %8
%14 = phi i8 [ %12, %8 ], [ -1, %5 ], [ %3, %1 ]
ret i8 %14
}